home *** CD-ROM | disk | FTP | other *** search
/ Best of www.BestZips.com (Collector's Edition) / Best of WWW.BESTZIPS.COM Collector's Edition (JCSM Shareware) (JCS Marketing).ISO / internet / zannetb1.zip / Zanserv.c < prev    next >
C/C++ Source or Header  |  1996-12-15  |  60KB  |  2,461 lines

  1.  
  2. #include <errno.h>
  3. #include <stdio.h>
  4. #include <unistd.h>
  5. #include <string.h>
  6. #include <memory.h>
  7. #include <sys/types.h>
  8. #include <dirent.h>
  9. #include <fcntl.h>
  10. #include <utime.h>
  11. #include "zanserv.h"
  12. #include <sys/socket.h>
  13. #include <netinet/in.h>
  14. #include <arpa/inet.h>
  15. #include <netdb.h>
  16.  
  17.  
  18. void ConnectToWindows ();
  19. void ProcessMessages ();
  20. void fsConfigure ();
  21. void fsOpenFile ();
  22. void fsCloseFile ();
  23. void fsReadFile ();
  24. void fsWriteFile ();
  25. void fsFileSeek ();
  26. void fsFindFirstFile ();
  27. void fsFindNextFile ();
  28. void fsFindClose ();
  29. void fsFileAttributes ();
  30. void fsDir ();
  31. void fsDeleteFile ();
  32. void fsRenameFile ();
  33. void fsGetDiskInfo ();
  34.  
  35. void fsWriteMoveEOF ();
  36. void ProcessDir ();
  37. int MakeNativePath ();
  38. int readn ();
  39. int writen ();
  40. int MetaMatch ();
  41. int MatchStarsAndQMs ();
  42. int FindSubPattern ();
  43. int CheckForExtension ();
  44. int CaseMatchDirectory ();
  45. char *zstrupr ();
  46. char *StripFileFromPath ();
  47. int FindSubPattern ();
  48. void NukeDotStar ();
  49. USHORT MapWindowsError ();
  50. int SetFilePosition ();
  51.  
  52. char    ProgramName[256];
  53. char    HomePath[MAX_PATH];
  54.  
  55. ULONG    ulMaxReaddirs = ZANNET_MAX_READDIRS;
  56. ULONG    ulDefaultAttributes = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
  57.  
  58. int        fDebug = TRUE;
  59.  
  60. char    InBuff[ZANSERV_IN_BUFFER_SIZE];
  61. char    OutBuff[ZANSERV_OUT_BUFFER_SIZE];
  62.  
  63. char    NativeSlash = '/';
  64. char    NativeSlashStr[] = "/";
  65. char    WindowsBSlash = '\\';
  66.  
  67. USHORT WindowsErrors[ESTALE+1] = 
  68. {
  69.     NO_ERROR,                    /* SUCCESS */
  70.     ERROR_INVALID_FUNCTION,        /* EPERM   1  Operation not permitted              */
  71.     ERROR_FILE_NOT_FOUND,        /* ENOENT  2  No such file or directory            */
  72.     ERROR_INVALID_FUNCTION,        /* ESRCH   3  No such process                      */
  73.     ERROR_UNEXP_NET_ERR,        /* EINTR   4  interrupted system call              */
  74.     ERROR_UNEXP_NET_ERR,        /* EIO     5  I/O error                            */
  75.     ERROR_UNEXP_NET_ERR,        /* ENXIO   6  No such device or address            */
  76.     ERROR_UNEXP_NET_ERR,        /* E2BIG   7  Arg list too long                    */
  77.     ERROR_UNEXP_NET_ERR,        /* ENOEXEC 8  Exec format error                    */
  78.     ERROR_INVALID_HANDLE,        /* EBADF   9  Bad file descriptor                  */
  79.     ERROR_UNEXP_NET_ERR,        /* ECHILD  10  No child processes                   */
  80.     ERROR_DEV_NOT_EXIST,        /* EAGAIN  11  Resource temporarily unavailable     */
  81.     ERROR_DISK_FULL,            /* ENOMEM  12  Not enough space                     */
  82.     ERROR_ACCESS_DENIED,        /* EACCES  13  Permission denied                    */
  83.     ERROR_INVALID_ADDRESS,        /* EFAULT  14  Bad address                          */
  84.     ERROR_UNEXP_NET_ERR,        /* ENOTBLK 15  Block device required                */
  85.     ERROR_NETWORK_BUSY,            /* EBUSY   16  Resource busy                        */
  86.     ERROR_FILE_EXISTS,            /* EEXIST  17  File exists                          */
  87.     ERROR_UNEXP_NET_ERR,        /* EXDEV   18  Improper link                        */
  88.     ERROR_UNEXP_NET_ERR,        /* ENODEV  19  No such device                       */
  89.     ERROR_DIRECTORY,            /* ENOTDIR 20  Not a directory                      */
  90.     ERROR_DIR_NOT_EMPTY,        /* EISDIR  21  Is a directory                       */
  91.     ERROR_BAD_ARGUMENTS,        /* EINVAL  22  Invalid argument                     */
  92.     ERROR_TOO_MANY_OPEN_FILES,    /* ENFILE  23  Too many open files in system        */
  93.     ERROR_TOO_MANY_OPEN_FILES,    /* EMFILE  24  Too many open files                  */
  94.     ERROR_UNEXP_NET_ERR,        /* ENOTTY  25  Inappropriate I/O control operation  */
  95.     ERROR_NETWORK_BUSY,            /* ETXTBSY 26  Text file busy                       */
  96.     ERROR_DISK_FULL,            /* EFBIG   27  File too large                       */
  97.     ERROR_DISK_FULL,            /* ENOSPC  28  No space left on device              */
  98.     ERROR_SEEK_ON_DEVICE,        /* ESPIPE  29  Invalid seek                         */
  99.     ERROR_ACCESS_DENIED,        /* EROFS   30  Read only file system                */
  100.     ERROR_UNEXP_NET_ERR,        /* EMLINK  31  Too many links                       */
  101.     ERROR_BROKEN_PIPE,            /* EPIPE   32  Broken pipe                          */
  102.     ERROR_UNEXP_NET_ERR,        /* EDOM    33  Domain error within math function    */
  103.     ERROR_UNEXP_NET_ERR,        /* ERANGE  34  Result too large                     */
  104.     ERROR_UNEXP_NET_ERR,        /* ENOMSG  35  No message of desired type           */
  105.     ERROR_UNEXP_NET_ERR,        /* EIDRM   36  Identifier removed                   */
  106.     ERROR_UNEXP_NET_ERR,        /* ECHRNG  37  Channel number out of range          */
  107.     ERROR_UNEXP_NET_ERR,        /* EL2NSYNC 38 Level 2 not synchronized             */
  108.     ERROR_UNEXP_NET_ERR,        /* EL3HLT  39  Level 3 halted                       */
  109.     ERROR_UNEXP_NET_ERR,        /* EL3RST  40  Level 3 reset                        */
  110.     ERROR_UNEXP_NET_ERR,        /* ELNRNG  41  Link number out of range             */
  111.     ERROR_UNEXP_NET_ERR,        /* EUNATCH 42  Protocol driver not attached         */
  112.     ERROR_UNEXP_NET_ERR,        /* ENOCSI  43  No CSI structure available           */
  113.     ERROR_UNEXP_NET_ERR,        /* EL2HLT  44  Level 2 halted                       */
  114.     ERROR_POSSIBLE_DEADLOCK,    /* EDEADLK 45  Resource deadlock avoided            */
  115.     ERROR_NOT_READY,            /* ENOTREADY   46  Device not ready                    */
  116.     ERROR_WRITE_PROTECT,        /* EWRPROTECT      47 Write-protected media        */
  117.     ERROR_NOT_DOS_DISK,            /* EFORMAT         48 Unformatted media            */
  118.     ERROR_LOCK_VIOLATION,        /* ENOLCK          49 No locks available           */
  119.     ERROR_UNEXP_NET_ERR,        /* ENOCONNECT      50 no connection                */
  120.     0,                            /* nothing         51  */
  121.     ERROR_NOT_DOS_DISK            /* ESTALE          52 no filesystem                */
  122. };
  123.  
  124.  
  125. main (argc, argv)
  126. int argc;
  127. char *argv[];
  128. {
  129.     char    hostIP[64];
  130.     char    hostName[MAX_PATH];
  131.     struct    hostent *pHostEntry;
  132.     int        port, sockfd;
  133.     struct    in_addr *pHostAddr;
  134.     char    *pEnv;
  135.  
  136.     /* First argument is IP address and second is port */
  137.  
  138.     if (argc != 3)
  139.     {
  140.         printf ("\nUsage: %s <IP Address> <Port>\n\n", argv[0]); 
  141.  
  142.         gethostname (hostName, sizeof(hostName));
  143.  
  144.         printf ("This machine's host name is: %s\n", hostName);
  145.  
  146.         if (pHostEntry = gethostbyname (hostName))
  147.         {
  148.             pHostAddr = (struct in_addr *)pHostEntry->h_addr;
  149.  
  150.             printf ("This machine's IP address is: %s\n\n", inet_ntoa(*pHostAddr));
  151.         }
  152.         exit (1);
  153.     }
  154.  
  155.     strcpy (ProgramName, argv[0]);
  156.     strcpy (hostIP, argv[1]);
  157.     port = atoi (argv[2]); 
  158.  
  159.     ConnectToWindows (hostIP, port, &sockfd);
  160.  
  161.     /* Don't change the below "CONNECT!" string....Windows looks for it!!!! */
  162.  
  163.     printf ("%s\n", ZANNET_CONNECT_STRING);
  164.     fflush (stdout);
  165.  
  166.     /* Set default home path */
  167.  
  168.     if (pEnv = (char *)getenv("HOME"))
  169.         strcpy (HomePath, pEnv);
  170.     else
  171.         strcpy (HomePath, "/");
  172.  
  173.     /* We handle all permission bits so turn off file creation mask */
  174.  
  175.     umask (~(S_IRWXU | S_IRWXG | S_IRWXO));
  176.  
  177.     ProcessMessages (sockfd);
  178.  
  179.     return 0;
  180. }
  181.  
  182.  
  183. /*
  184. *  Connect to the Windows 95 machine 
  185. */
  186. void ConnectToWindows (hostIP, port, sockfd)
  187. char hostIP[];
  188. int port;
  189. int *sockfd;
  190. {
  191.     struct    sockaddr_in    serv_addr;
  192.  
  193.     /* Open the socket */
  194.  
  195.     memset ((char *)&serv_addr, 0, sizeof(serv_addr));
  196.  
  197.     serv_addr.sin_family = AF_INET;
  198.     serv_addr.sin_addr.s_addr = inet_addr (hostIP);
  199.     serv_addr.sin_port = htons (port);
  200.  
  201.     if ((*sockfd = socket (AF_INET, SOCK_STREAM, 0)) < 0)
  202.     {
  203.         !fDebug ? 0 : printf ("%s Socket Error:  socket(), rc = %d\n", ProgramName, errno);
  204.         exit (1);
  205.     }
  206.  
  207.         /* Connect to Windows Server */
  208.  
  209.     if (connect (*sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0)
  210.     {
  211.         !fDebug ? 0 : printf ("%s Socket Error:  connect(), port = %d, rc = %d, ip = %s\n", 
  212.             ProgramName, port, errno, hostIP);
  213.  
  214.         exit (1);
  215.     }
  216. }
  217.  
  218.  
  219. /*
  220. *  Process Windows file system commands
  221. */
  222. void ProcessMessages (sockfd)
  223. int sockfd;
  224. {
  225.     winio_generic    *pwinGen;
  226.     int                iBytesRead;
  227.     pwinGen = (winio_generic *)InBuff;
  228.  
  229.     while (iBytesRead = readn(sockfd, pwinGen, sizeof(winio_generic)))
  230.     {
  231.         /* First read the generic packet (above) and get the length */
  232.  
  233.         if (iBytesRead < sizeof(winio_generic))
  234.         {
  235.             !fDebug ? 0 : printf ("%s error. First readn() = %d\n", iBytesRead);
  236.             exit (1);
  237.         }
  238.  
  239.         pwinGen->usType = ntohs(pwinGen->usType);
  240.         pwinGen->usLen = ntohs(pwinGen->usLen);
  241.         pwinGen->ulFlags = ntohl(pwinGen->ulFlags);
  242.  
  243.         /*
  244.         !fDebug ? 0 : printf ("Got Generic, type = %d, reading len = %d\n", 
  245.             pwinGen->usType, (int)(pwinGen->usLen - sizeof(winio_generic)));
  246.         */
  247.  
  248.         /* Now read the full packet */
  249.         
  250.         iBytesRead = readn (sockfd, &InBuff[sizeof(winio_generic)], 
  251.             pwinGen->usLen - sizeof(winio_generic));
  252.  
  253.         if (iBytesRead < (pwinGen->usLen - sizeof(winio_generic)))
  254.         {
  255.             !fDebug ? 0 : printf ("%s error. Second readn() = %d\n", iBytesRead);
  256.             exit (1);
  257.         }
  258.  
  259.         switch (pwinGen->usType)
  260.         {
  261.         case FS_CONFIGURE:
  262.             fsConfigure (sockfd, InBuff);
  263.             break;
  264.         case FS_OPENFILE:
  265.             fsOpenFile (sockfd, InBuff);
  266.             break;
  267.         case FS_CLOSEFILE:
  268.             fsCloseFile (sockfd, InBuff);
  269.             break;
  270.         case FS_READFILE:
  271.             fsReadFile (sockfd, InBuff);
  272.             break;
  273.         case FS_WRITEFILE:
  274.             fsWriteFile (sockfd, InBuff);
  275.             break;
  276.         case FS_FILESEEK:
  277.             fsFileSeek (sockfd, InBuff);
  278.             break;
  279.         case FS_FINDFIRSTFILE:
  280.             fsFindFirstFile (sockfd, InBuff);
  281.             break;
  282.         case FS_FINDNEXTFILE:
  283.             fsFindNextFile (sockfd, InBuff);
  284.             break;
  285.         case FS_FINDCLOSE:
  286.             fsFindClose (sockfd, InBuff);
  287.             break;
  288.         case FS_FILEATTRIBUTES:
  289.             fsFileAttributes (sockfd, InBuff);
  290.             break;
  291.         case FS_DIR:
  292.             fsDir (sockfd, InBuff);
  293.             break;
  294.         case FS_DELETEFILE:
  295.             fsDeleteFile (sockfd, InBuff);
  296.             break;
  297.         case FS_RENAMEFILE:
  298.             fsRenameFile (sockfd, InBuff);
  299.             break;
  300.         case FS_GETDISKINFO:
  301.             fsGetDiskInfo (sockfd, InBuff);
  302.             break;
  303.         default:
  304.             !fDebug ? 0 : printf ("%s Unknown Command:  Command = %d\n", pwinGen->usType);
  305.         }
  306.     }
  307. }
  308.  
  309.  
  310. /*
  311. *  Configuration and shutdown
  312. */
  313. void fsConfigure (sockfd, pInBuff)
  314. int sockfd;
  315. char *pInBuff;
  316. {
  317.     fs_configure        *pConfig;
  318.     fs_configureAck        *pConfigAck;
  319.     struct stat            fStat;
  320.     USHORT                usLen;
  321.  
  322.     pConfigAck = (fs_configureAck *)OutBuff;
  323.     memset ((char *)pConfigAck, 0, sizeof(fs_configureAck));
  324.  
  325.     pConfigAck->usVersionMajor = htons(ZANNET_VERSION_MAJOR);
  326.     pConfigAck->usVersionMinor = htons(ZANNET_VERSION_MINOR);
  327.  
  328.     pConfig = (fs_configure *)pInBuff;
  329.  
  330.     pConfig->ulServerDefaultAttribs = ntohl(pConfig->ulServerDefaultAttribs);
  331.     pConfig->ulMaxReaddirs = ntohl(pConfig->ulMaxReaddirs);
  332.     pConfig->sPathLen = ntohs(pConfig->sPathLen);
  333.  
  334.     !fDebug ? 0 : printf ("FS_CONFIGURE: \n");
  335.  
  336.     if (pConfig->ulFlags & ZANSERV_DEBUG_ON)
  337.     {
  338.         fDebug = TRUE;
  339.         !fDebug ? 0 : printf ("Debug On!\n");
  340.     }
  341.  
  342.     if (pConfig->ulFlags & ZANSERV_DEBUG_OFF)
  343.     {
  344.         !fDebug ? 0 : printf ("Debug Off!\n");
  345.         fDebug = FALSE;
  346.     }
  347.  
  348.     if (pConfig->ulFlags & ZANSERV_MAX_READDIRS)
  349.     {
  350.         !fDebug ? 0 : printf ("ZANSERV_MAX_READDIRS = %d\n", pConfig->ulMaxReaddirs);
  351.         fflush(stdout);
  352.  
  353.         ulMaxReaddirs = pConfig->ulMaxReaddirs;
  354.     }
  355.  
  356.     if (pConfig->ulFlags & ZANSERV_NEW_HOME)
  357.     {
  358.         !fDebug ? 0 : printf ("ZANSERV_NEW_HOME: %s\n", pConfig->HomePath);
  359.  
  360.         if (!stat(pConfig->HomePath, &fStat))
  361.         {
  362.             strcpy (HomePath, pConfig->HomePath);
  363.         }
  364.         else
  365.         {
  366.             pConfigAck->rc = ERROR_FILE_NOT_FOUND;
  367.             !fDebug ? 0 : printf ("***** Can't find new home directory: %s\n", pConfig->HomePath);
  368.         }
  369.     }
  370.  
  371.     if (pConfig->ulFlags & ZANSERV_ATTRIBS)
  372.     {
  373.         !fDebug ? 0 : printf ("ZANSERV_ATTRIBS: %x\n", pConfig->ulServerDefaultAttribs);
  374.  
  375.         ulDefaultAttributes = pConfig->ulServerDefaultAttribs;
  376.     }
  377.  
  378.     /* Write the results to Windows */
  379.  
  380.     if (pConfig->ulFlags & ZANSERV_PING)
  381.     {
  382.         usLen = pConfig->usLen;
  383.  
  384.         !fDebug ? 0 : printf ("ZANSERV_PING: Sending %d bytes\n", usLen);
  385.  
  386.         memcpy (&OutBuff[sizeof(fs_configureAck)], pConfig->HomePath, usLen);
  387.     }
  388.     else
  389.         usLen = sizeof(fs_configureAck);
  390.  
  391.     pConfigAck->usLen = htons(usLen);
  392.  
  393.     pConfigAck->usType = htons(pConfig->usType);
  394.     pConfigAck->rc = htonl(pConfigAck->rc);
  395.  
  396.     pConfigAck->ulKey = pConfig->ulKey;
  397.  
  398.     /* Shutdown if requested. This is ACKed by the Windows socket disconnect */
  399.  
  400.     if (pConfig->ulFlags & ZANSERV_SHUTDOWN)
  401.     {
  402.         !fDebug ? 0 : printf ("Normal Shutdown with flag: ZANSERV_SHUTDOWN\n");
  403.         close (sockfd);
  404.         exit (0);
  405.     }
  406.  
  407.     writen (sockfd, pConfigAck, usLen);
  408.  
  409.     !fDebug ? 0 : printf ("FS_CONFIGURE: rc=%d\n", ntohl(pConfigAck->rc));
  410. }
  411.  
  412.  
  413. /*
  414. *  Open file
  415. */
  416. void fsOpenFile (sockfd, pInBuff)
  417. int sockfd;
  418. char *pInBuff;
  419. {
  420.     fs_openfile            *pOpen;
  421.     fs_openfileAck        *pOpenAck;
  422.     struct stat            fStat;
  423.     int                    iflags = 0; 
  424.     mode_t                mode = 0;
  425.     char                NATIVEPath[MAX_PATH];
  426.  
  427.     pOpen = (fs_openfile *)pInBuff;
  428.  
  429.     pOpen->ulAttribs = ntohl(pOpen->ulAttribs);
  430.     pOpen->usOptions = ntohs(pOpen->usOptions);
  431.     pOpen->sPathLen = ntohs(pOpen->sPathLen);
  432.  
  433.     !fDebug ? 0 : printf ("FS_OPENFILE: Flags=%x, Attribs=%x, Options=%x, Path=%s\n",
  434.         pOpen->ulFlags, pOpen->ulAttribs, pOpen->usOptions, pOpen->Path);
  435.  
  436.     pOpenAck = (fs_openfileAck *)OutBuff;
  437.     memset ((char *)pOpenAck, 0, sizeof(fs_openfileAck));
  438.  
  439.     /* Translate Windows flags to POSIX */
  440.  
  441.     switch (pOpen->ulFlags & ACCESS_MODE_MASK)
  442.     {
  443.     case ACCESS_READONLY:
  444.         iflags |= O_RDONLY;
  445.         break;
  446.     case ACCESS_WRITEONLY:
  447.         iflags |= O_WRONLY;
  448.         break;
  449.     case ACCESS_READWRITE:
  450.         iflags |= O_RDWR;
  451.         break;
  452.     case ACCESS_EXECUTE:
  453.         iflags |= O_RDONLY;
  454.         break;
  455.     default:
  456.         iflags |= O_RDONLY;
  457.     }
  458.  
  459.     /***
  460.  
  461.     Sharing flags are NOT yet supported. All files are considered
  462.     read/write shareable at this time - 11/21/96 
  463.  
  464.       switch (pOpen->ulFlags & SHARE_MODE_MASK)
  465.     {
  466.     case SHARE_COMPATIBILITY:
  467.         break;
  468.     case SHARE_DENYREADWRITE:
  469.         break;
  470.     case SHARE_DENYWRITE:
  471.         break;
  472.     case SHARE_DENYREAD:
  473.         break;
  474.     default:
  475.     }
  476.  
  477.     ***/
  478.  
  479.     /* Get the path squared away */
  480.  
  481.     if (pOpenAck->rc = MakeNativePath (pOpen->Path, NATIVEPath, pOpen->ulAttribs))
  482.         goto ExitfsOpenFile;
  483.         
  484.     /* Next are the Windows options. Note: mode is ignored if file already
  485.        exists! */
  486.  
  487.     switch (pOpen->usOptions & ACTION_MASK)
  488.     {
  489.     case ACTION_CREATEALWAYS:
  490.     {
  491.         /* Create a new file. If the file already exists open it and set
  492.         its new length and attributes */
  493.  
  494.         iflags |= O_CREAT | O_TRUNC;
  495.         
  496.         if (pOpen->ulAttribs & FILE_ATTRIBUTE_READONLY)
  497.             mode = ulDefaultAttributes & ~(S_IWUSR | S_IWGRP | S_IWOTH);
  498.         else 
  499.             mode = ulDefaultAttributes;
  500.  
  501.         if (!(stat(NATIVEPath, &fStat)))
  502.         {
  503.             /* File already exists, set new attributes */
  504.  
  505.             if (chmod (NATIVEPath, mode) < 0)
  506.             {
  507.                 pOpenAck->rc = MapWindowsError (errno);
  508.             }
  509.             else
  510.                 pOpenAck->usAction = ACTION_OPENED;
  511.  
  512.             mode = 0;
  513.         }
  514.         else
  515.             pOpenAck->usAction = ACTION_CREATED;
  516.  
  517.         break;
  518.     }
  519.     case ACTION_OPENALWAYS:
  520.     {
  521.         /* Open an existing file. If the file does not exist, create a new file */
  522.  
  523.         if (stat(NATIVEPath, &fStat))
  524.         {
  525.             /* No existing file, set mode for file creation */
  526.  
  527.             if (pOpen->ulAttribs & FILE_ATTRIBUTE_READONLY)
  528.                 mode = ulDefaultAttributes & ~(S_IWUSR | S_IWGRP | S_IWOTH);
  529.             else 
  530.                 mode = ulDefaultAttributes;
  531.  
  532.             pOpenAck->usAction = ACTION_CREATED;
  533.         }
  534.         else
  535.             pOpenAck->usAction = ACTION_OPENED;
  536.  
  537.         iflags |= O_CREAT;
  538.         break;
  539.     }
  540.     case ACTION_CREATENEW:
  541.     {
  542.         /* Create a new file. Fail if the file already exists */
  543.  
  544.         if (pOpen->ulAttribs & FILE_ATTRIBUTE_READONLY)
  545.             mode = ulDefaultAttributes & ~(S_IWUSR | S_IWGRP | S_IWOTH);
  546.         else 
  547.             mode = ulDefaultAttributes;
  548.  
  549.         iflags |= O_CREAT | O_EXCL;
  550.  
  551.         pOpenAck->usAction = ACTION_CREATED;
  552.  
  553.         break;
  554.     }
  555.     case ACTION_REPLACEEXISTING:
  556.     {
  557.         /* Open an existing file and set its new length. Fail if the file does not exist */
  558.  
  559.         iflags |= O_TRUNC;
  560.  
  561.         if (stat(NATIVEPath, &fStat))
  562.         {
  563.             /* No existing file, set error */
  564.  
  565.             pOpenAck->rc = ERROR_FILE_NOT_FOUND;
  566.         }
  567.         else
  568.             pOpenAck->usAction = ACTION_REPLACED;
  569.  
  570.         break;
  571.     }
  572.     case ACTION_OPENEXISTING:
  573.     {
  574.         /* Open an existing file. Fail if the file does not exist */
  575.  
  576.         pOpenAck->usAction = ACTION_OPENED;
  577.         break;
  578.     }
  579.     default:
  580.     {
  581.         /* Open an existing file. Fail if the file does not exist */
  582.  
  583.         pOpenAck->usAction = ACTION_OPENED;
  584.         break;
  585.     }
  586.     }
  587.  
  588.     /* Make sure this is not a directory */
  589.  
  590.     if (!stat(NATIVEPath, &fStat))
  591.     {
  592.         if (S_ISDIR(fStat.st_mode))
  593.             pOpenAck->rc = ERROR_ACCESS_DENIED;
  594.     }
  595.  
  596.     if (!pOpenAck->rc)
  597.     {
  598.         if (mode)
  599.             pOpenAck->iFileHandle = open (NATIVEPath, iflags, mode);
  600.         else
  601.             pOpenAck->iFileHandle = open (NATIVEPath, iflags);
  602.  
  603.         if (pOpenAck->iFileHandle > 0)
  604.         {
  605.             /* Get the length, last modification date/time and attributes */
  606.  
  607.             if (!(stat(NATIVEPath, &fStat)))
  608.             {
  609.                 pOpenAck->ulSize = fStat.st_size;
  610.                 pOpenAck->LastAccess = fStat.st_mtime;
  611.  
  612.                 if ((fStat.st_mode & S_IRUSR) && !(fStat.st_mode & S_IWUSR))
  613.                 {
  614.                     /* !fDebug ? 0 : printf ("Open file as read only\n"); */
  615.                     pOpenAck->ulAttribs = FILE_ATTRIBUTE_READONLY;
  616.                 }
  617.                 else
  618.                 {
  619.                     /* !fDebug ? 0 : printf ("Open file normal\n"); */
  620.                     /* pOpenAck->ulAttribs = FILE_ATTRIBUTE_ARCHIVE; */
  621.                     pOpenAck->ulAttribs = 0;
  622.                 }
  623.             }
  624.             else 
  625.             {
  626.                 pOpenAck->usAction = 0;
  627.                 pOpenAck->rc = MapWindowsError (errno);
  628.             }
  629.         }
  630.         else
  631.         {
  632.             pOpenAck->usAction = 0;
  633.             pOpenAck->rc = MapWindowsError (errno);
  634.         }
  635.     }
  636.  
  637. ExitfsOpenFile:
  638.  
  639.     /* Write the results to Windows */
  640.  
  641.     pOpenAck->ulFlags = htonl(pOpenAck->ulFlags);
  642.     pOpenAck->ulAttribs = htonl(pOpenAck->ulAttribs);
  643.     pOpenAck->LastAccess = htonl(pOpenAck->LastAccess);
  644.     pOpenAck->ulSize = htonl(pOpenAck->ulSize);
  645.     pOpenAck->rc = htons(pOpenAck->rc);
  646.     pOpenAck->usAction = htons(pOpenAck->usAction);
  647.  
  648.     pOpenAck->usLen = htons(sizeof(fs_openfileAck));
  649.     pOpenAck->usType = htons(pOpen->usType);
  650.  
  651.     pOpenAck->ulKey = pOpen->ulKey;
  652.  
  653.     writen (sockfd, pOpenAck, sizeof(fs_openfileAck));
  654.  
  655.     !fDebug ? 0 : printf ("FS_OPENFILE: rc=%d, action=%d, size=%d, attrib=%x\n", 
  656.         htons(pOpenAck->rc), htons(pOpenAck->usAction), htonl(pOpenAck->ulSize),
  657.         htonl(pOpenAck->ulAttribs));
  658. }
  659.  
  660.  
  661. /*
  662. *  Close file
  663. */
  664. void fsCloseFile (sockfd, pInBuff)
  665. int sockfd;
  666. char *pInBuff;
  667. {
  668.     fs_close        *pClose;
  669.     fs_closeAck        *pCloseAck;
  670.  
  671.     pClose = (fs_close *)pInBuff;
  672.  
  673.     !fDebug ? 0 : printf ("FS_CLOSEFILE: Handle=%d\n", pClose->iFileHandle); 
  674.         
  675.     pCloseAck = (fs_closeAck *)OutBuff;
  676.     memset ((char *)pCloseAck, 0, sizeof(fs_closeAck));
  677.     
  678.     if (close (pClose->iFileHandle) < 0)
  679.         pCloseAck->rc = MapWindowsError (errno);
  680.  
  681.     pCloseAck->usLen = htons(sizeof(fs_closeAck));
  682.     pCloseAck->usType = htons(pClose->usType);
  683.     pCloseAck->ulKey = pClose->ulKey;
  684.  
  685.     pCloseAck->rc = htons(pCloseAck->rc);
  686.  
  687.     writen (sockfd, pCloseAck, sizeof(fs_closeAck));
  688.  
  689.     !fDebug ? 0 : printf ("FS_CLOSEFILE: rc=%d\n", ntohs(pCloseAck->rc));
  690. }
  691.  
  692.  
  693. /*
  694. *  Read file
  695. */
  696. void fsReadFile (sockfd, pInBuff)
  697. int sockfd;
  698. char *pInBuff;
  699. {
  700.     fs_readfile        *pRead;
  701.     fs_readfileAck    *pReadAck;
  702.     USHORT            usWriteLen;
  703.  
  704.     pRead = (fs_readfile *)pInBuff;
  705.  
  706.     pRead->iLength = ntohl(pRead->iLength);
  707.     pRead->lPosition = ntohl(pRead->lPosition);
  708.  
  709.     !fDebug ? 0 : printf ("FS_READFILE: Handle=%d, Length=%d, Position=%d\n",
  710.         pRead->iFileHandle, pRead->iLength, pRead->lPosition);
  711.  
  712.     pReadAck = (fs_readfileAck *)OutBuff;
  713.     memset ((char *)pReadAck, 0, sizeof(fs_readfileAck));
  714.  
  715.     /* Make sure we are in the correct position */
  716.  
  717.     pReadAck->rc = SetFilePosition (pRead->iFileHandle, pRead->lPosition);
  718.     
  719.     if (!pReadAck->rc)
  720.     {
  721.         pReadAck->lPosition = pRead->lPosition;
  722.  
  723.         /* Do the NATIVE file read */
  724.  
  725.         pReadAck->iLength = readn (pRead->iFileHandle, pReadAck->Data, pRead->iLength);
  726.             
  727.         if (pReadAck->iLength < 0)
  728.         {
  729.             pReadAck->rc = MapWindowsError (errno);
  730.             pReadAck->iLength = 0;
  731.         }
  732.         else
  733.             pReadAck->lPosition += pReadAck->iLength;
  734.     }
  735.  
  736.     /* Write the packet and data to Windows */
  737.  
  738.     usWriteLen = sizeof(fs_readfileAck) + pReadAck->iLength - sizeof(pReadAck->Data);
  739.  
  740.     pReadAck->usLen = htons(usWriteLen);
  741.     pReadAck->ulKey = pRead->ulKey;
  742.     pReadAck->usType = htons(pRead->usType);
  743.  
  744.     pReadAck->iLength = htonl(pReadAck->iLength);
  745.     pReadAck->lPosition = htonl(pReadAck->lPosition);
  746.     pReadAck->rc = htons(pReadAck->rc);
  747.  
  748.     writen (sockfd, pReadAck, usWriteLen);
  749.  
  750.     !fDebug ? 0 : printf ("FS_READFILE: rc=%d, len=%d, pos=%d\n", 
  751.         ntohs(pReadAck->rc), ntohl(pReadAck->iLength), ntohl(pReadAck->lPosition));
  752. }
  753.  
  754.  
  755. /*
  756. *  Write file
  757. */
  758. void fsWriteFile (sockfd, pInBuff)
  759. int sockfd;
  760. char *pInBuff;
  761. {
  762.     fs_writefile        *pWrite;
  763.     fs_writefileAck        *pWriteAck;
  764.     
  765.  
  766.     pWrite = (fs_writefile *)pInBuff;
  767.  
  768.     pWrite->iLength = ntohl(pWrite->iLength);
  769.     pWrite->lPosition = ntohl(pWrite->lPosition);
  770.  
  771.     !fDebug ? 0 : printf ("FS_WRITEFILE: Handle=%d, Length=%d, Position=%d\n",
  772.         pWrite->iFileHandle, pWrite->iLength, pWrite->lPosition);
  773.  
  774.     pWriteAck = (fs_writefileAck *)OutBuff;
  775.     memset ((char *)pWriteAck, 0, sizeof(fs_writefileAck));
  776.  
  777.     if (!pWrite->iLength)
  778.         pWriteAck->rc = ERROR_BAD_ARGUMENTS;
  779.  
  780.     if (pWrite->ulFlags & ZANSERV_FSWRITE_MOVE_EOF && !pWriteAck->rc)
  781.     {
  782.         fsWriteMoveEOF (pWrite, pWriteAck);
  783.     }
  784.     else if (!pWriteAck->rc)
  785.     {
  786.         /* Make sure we are in the correct position */
  787.  
  788.         pWriteAck->rc = SetFilePosition (pWrite->iFileHandle, pWrite->lPosition);
  789.  
  790.         if (!pWriteAck->rc)
  791.         {
  792.             pWriteAck->lPosition = pWrite->lPosition;
  793.  
  794.             /* Do the NATIVE file write */
  795.  
  796.             pWriteAck->iBytesWritten = writen (pWrite->iFileHandle, pWrite->WriteData, pWrite->iLength);
  797.                 
  798.             if (pWriteAck->iBytesWritten < 0)
  799.                 pWriteAck->rc = MapWindowsError (errno);
  800.             else    
  801.                 pWriteAck->lPosition += pWriteAck->iBytesWritten;
  802.         }
  803.     }
  804.  
  805.     /* Return status to Windows */
  806.  
  807.     pWriteAck->rc = htons(pWriteAck->rc);
  808.     pWriteAck->usLen = htons(sizeof(fs_writefileAck));
  809.     pWriteAck->ulKey = pWrite->ulKey;
  810.     pWriteAck->usType = htons(pWrite->usType);
  811.  
  812.     pWriteAck->iBytesWritten = htonl(pWriteAck->iBytesWritten);
  813.     pWriteAck->lPosition = htonl(pWriteAck->lPosition);
  814.  
  815.     writen (sockfd, pWriteAck, sizeof(fs_writefileAck));
  816.  
  817.     !fDebug ? 0 : printf ("FS_WRITEFILE: rc=%d, len=%d, pos=%d\n", 
  818.         ntohs(pWriteAck->rc), ntohl(pWriteAck->iBytesWritten), ntohl(pWriteAck->lPosition));
  819. }
  820.  
  821.  
  822. /*
  823. *  fsWriteMoveEOF
  824. */
  825. void fsWriteMoveEOF (pWrite, pWriteAck)
  826. fs_writefile *pWrite;
  827. fs_writefileAck *pWriteAck;
  828. {
  829.     struct    stat    fStat;
  830.     char    WritePad[0xFFFF];
  831.     char    NATIVEPath[MAX_PATH];
  832.     char    TmpFileName[MAX_PATH];
  833.     int        lPos=0, lWritten=0, lDiff, lRead=0;
  834.     FILE    *fpNew, *fpOld;
  835.     int        NewDesc1, NewDesc2;
  836.  
  837.     /* A zero length write is used by Windows to set a new 
  838.     EOF position. A    real PintheA for us here. Just do it! */
  839.  
  840.     if (!(fstat (pWrite->iFileHandle, &fStat)))
  841.     {
  842.         if ((fStat.st_mode & S_IRUSR) && !(fStat.st_mode & S_IWUSR))
  843.         {
  844.             pWriteAck->rc = ERROR_ACCESS_DENIED;
  845.             return;
  846.         }
  847.         if (fStat.st_size > pWrite->lPosition)
  848.         {
  849.             /* A truncation request, copy the file up to new EOF */
  850.  
  851.             close (pWrite->iFileHandle);
  852.  
  853.             MakeNativePath (pWrite->WriteData, NATIVEPath, pWrite->ulFlags);
  854.  
  855.             !fDebug ? 0 : printf ("FS_WRITEFILE: Truncation - path = %s\n", NATIVEPath);
  856.  
  857.             /* Rename it to something unique */
  858.  
  859.             strcpy (TmpFileName, NATIVEPath);
  860.             strcat (TmpFileName, "_ZNet");
  861.  
  862.             if (rename (NATIVEPath, TmpFileName))
  863.             {
  864.                 pWriteAck->rc = MapWindowsError (errno);
  865.             }
  866.             else
  867.             {
  868.                 /* Open new file and old file as streams */
  869.  
  870.                 if (!(fpNew = fopen (NATIVEPath, "w+")))
  871.                 {
  872.                     pWriteAck->rc = MapWindowsError (errno);
  873.                 }
  874.                 else
  875.                 {
  876.                     if (!(fpOld = fopen (TmpFileName, "r")))
  877.                     {
  878.                         fclose (fpNew);
  879.                         pWriteAck->rc = MapWindowsError (errno);
  880.                     }
  881.                     else
  882.                     {
  883.                         /* Copy up to the new EOF */
  884.  
  885.                         while (lPos < pWrite->lPosition)
  886.                         {
  887.                             lDiff = pWrite->lPosition - lPos;
  888.  
  889.                             lRead = fread (WritePad, 1, lDiff < sizeof(WritePad) ? lDiff : sizeof(WritePad), fpOld);
  890.  
  891.                             if (lRead < 0)
  892.                             {
  893.                                 pWriteAck->rc = MapWindowsError (errno);
  894.                                 break;
  895.                             }
  896.  
  897.                             lWritten = fwrite (WritePad, 1, lRead, fpNew);
  898.  
  899.                             if (lWritten < 0)
  900.                             {
  901.                                 pWriteAck->rc = MapWindowsError (errno);
  902.                                 break;
  903.                             }
  904.                             else    
  905.                                 lPos += lWritten;
  906.                         }
  907.  
  908.                         /* Close the streams */
  909.  
  910.                         fclose (fpOld);
  911.                         fclose (fpNew);
  912.  
  913.                         /* Set the orginal file mode */
  914.  
  915.                         chmod (NATIVEPath, fStat.st_mode);
  916.                         
  917.                         if (!pWriteAck->rc)
  918.                         {
  919.                             /* Delete the tmp file */
  920.  
  921.                             unlink (TmpFileName);
  922.  
  923.                             /* Get back our original file descriptor or else Windows will have a cow */
  924.  
  925.                             if ((NewDesc1 = open (NATIVEPath, O_RDWR)) < 0)
  926.                             {
  927.                                 pWriteAck->rc = MapWindowsError (errno);
  928.                             }
  929.                             else if (NewDesc1 != pWrite->iFileHandle)
  930.                             {
  931.                                 if ((NewDesc2 = fcntl(NewDesc1, F_DUPFD, pWrite->iFileHandle)) < 0)
  932.                                 {
  933.                                     pWriteAck->rc = MapWindowsError (errno);
  934.                                 }
  935.                                 else if (NewDesc2 != pWrite->iFileHandle)
  936.                                 {
  937.                                     pWriteAck->rc = ERROR_WRITE_FAULT;
  938.                                     close (NewDesc2);
  939.                                 }
  940.                                 close (NewDesc1);
  941.                             }
  942.                         }
  943.                     }
  944.                 }
  945.             }
  946.             if (!pWriteAck->rc)
  947.                 pWriteAck->lPosition = pWrite->lPosition;
  948.         }
  949.         else
  950.         {
  951.             !fDebug ? 0 : printf ("FS_WRITEFILE: Expansion\n");
  952.  
  953.             /* Grow the file */
  954.  
  955.             memset (WritePad, 0, sizeof(WritePad));
  956.  
  957.             if ((lPos = lseek (pWrite->iFileHandle, 0, SEEK_END)) < 0)
  958.                 pWriteAck->rc = MapWindowsError (errno);
  959.             else
  960.             {
  961.                 while (lPos < pWrite->lPosition)
  962.                 {
  963.                     lDiff = pWrite->lPosition - lPos;
  964.  
  965.                     lWritten = writen (pWrite->iFileHandle, WritePad, lDiff < sizeof(WritePad) ? lDiff : sizeof(WritePad));
  966.                     
  967.                     if (lWritten < 0)
  968.                     {
  969.                         !fDebug ? 0 : printf ("FS_WRITEFILE: error = %d\n", errno);
  970.                         pWriteAck->rc = MapWindowsError (errno);
  971.                         break;
  972.                     }
  973.                     else    
  974.                         lPos += lWritten;
  975.                 }
  976.                 if (!pWriteAck->rc)
  977.                     pWriteAck->lPosition = lPos;
  978.             }
  979.         }
  980.     }
  981.     else
  982.         pWriteAck->rc = ERROR_INVALID_HANDLE;
  983. }
  984.  
  985.  
  986. /*
  987. *  Seek file - Note: A "seek" is really meaningless because all reads and writes 
  988. *              come with length and offset. Just return the proper file size. The
  989. *              seek is performed on the server for the sake of error checking. FILE_BEGIN
  990. *              will never even get here because it is handled in Windows only.
  991. */
  992. void fsFileSeek (sockfd, pInBuff)
  993. int sockfd;
  994. char *pInBuff;
  995. {
  996.     fs_fileseek        *pSeek;
  997.     fs_fileseekAck    *pSeekAck;
  998.     int                iwhence = -1, DoSeek=TRUE;
  999.     struct            stat    fStat;
  1000.  
  1001.     pSeek = (fs_fileseek *)pInBuff;
  1002.  
  1003.     pSeek->lSeekOffset = ntohl(pSeek->lSeekOffset);
  1004.  
  1005.     !fDebug ? 0 : printf ("FS_FILESEEK: Handle=%d, Flags=%d, Offset=%d\n",
  1006.         pSeek->iFileHandle, pSeek->ulFlags, pSeek->lSeekOffset);
  1007.  
  1008.     pSeekAck = (fs_fileseekAck *)OutBuff;
  1009.     memset ((char *)pSeekAck, 0, sizeof(fs_fileseekAck));
  1010.  
  1011.     if (fstat(pSeek->iFileHandle, &fStat) < 0)
  1012.         pSeekAck->rc = MapWindowsError(errno);
  1013.  
  1014.     if (pSeek->ulFlags == FILE_BEGIN)
  1015.     {
  1016.         iwhence = SEEK_SET;
  1017.     }
  1018.     else if (pSeek->ulFlags == FILE_END)
  1019.     {
  1020.         if ((fStat.st_size + pSeek->lSeekOffset) < 0)
  1021.         {
  1022.             DoSeek = FALSE;
  1023.             pSeekAck->lSeekOffset = fStat.st_size + pSeek->lSeekOffset;
  1024.         }
  1025.         iwhence = SEEK_END;
  1026.     }
  1027.     else
  1028.         pSeekAck->rc = ERROR_SEEK_ON_DEVICE;
  1029.  
  1030.     if (!pSeekAck->rc)
  1031.     {
  1032.         if (DoSeek)
  1033.         {
  1034.             pSeekAck->lSeekOffset = lseek (pSeek->iFileHandle, pSeek->lSeekOffset, iwhence);
  1035.  
  1036.             if (pSeekAck->lSeekOffset < 0)
  1037.                 pSeekAck->rc = MapWindowsError (errno);
  1038.         }
  1039.     }
  1040.  
  1041.     pSeekAck->usLen = htons(sizeof(fs_fileseekAck));
  1042.     pSeekAck->ulKey = pSeek->ulKey;
  1043.     pSeekAck->usType = htons(pSeek->usType);
  1044.  
  1045.     pSeekAck->lSeekOffset = htonl(pSeekAck->lSeekOffset);
  1046.     pSeekAck->rc = htons(pSeekAck->rc);
  1047.  
  1048.     writen (sockfd, pSeekAck, sizeof(fs_fileseekAck));
  1049.  
  1050.     !fDebug ? 0 : printf ("FS_FILESEEK: rc=%d, offset=%d\n", 
  1051.         ntohs(pSeekAck->rc), ntohl(pSeekAck->lSeekOffset));
  1052. }
  1053.  
  1054.  
  1055. /*
  1056. * fsFindFirstFile
  1057. */
  1058. void fsFindFirstFile (sockfd, pInBuff)
  1059. int sockfd;
  1060. char *pInBuff;
  1061. {
  1062.     fs_findfirstfile        *pFFirst;
  1063.     fs_findfirstfileAck        *pFFirstAck;
  1064.     DIR                        *pDir=0;
  1065.     char                    NATIVEPath[MAX_PATH];
  1066.     fs_findfileinfo            *pffInfo=0;
  1067.     char                    *pSearchPattern=0, *pFile=0;
  1068.     int                        isRoot=FALSE;
  1069.     USHORT                    usWriteLen;
  1070.  
  1071.     /* Read the find first structure */
  1072.  
  1073.     pFFirst = (fs_findfirstfile *)pInBuff;
  1074.  
  1075.     pFFirst->ulRetBufLen = ntohl(pFFirst->ulRetBufLen);
  1076.     pFFirst->sPathLen = ntohs(pFFirst->sPathLen);
  1077.     pFFirst->ulAttrib &= ~FILE_FLAG_KEEP_CASE;
  1078.  
  1079.     !fDebug ? 0 : printf ("FS_FINDFIRSTFILE: Attribs=%x, BuffLen=%d, Path=%s\n",
  1080.         pFFirst->ulAttrib, pFFirst->ulRetBufLen, pFFirst->Path);
  1081.  
  1082.     pFFirstAck = (fs_findfirstfileAck *)OutBuff;
  1083.     memset ((char *)pFFirstAck, 0, sizeof(fs_findfirstfileAck));
  1084.     
  1085.     if (pFFirst->ulAttrib & FILE_FLAG_WILDCARDS || pFFirst->ulAttrib & FILE_FLAG_HAS_STAR)
  1086.     {
  1087.         /* This is a search pattern - strip it */
  1088.  
  1089.         /* !fDebug ? 0 : printf ("Found wildcard chars\n"); */
  1090.  
  1091.         pSearchPattern = StripFileFromPath (pFFirst->Path, WindowsBSlash);
  1092.  
  1093.         if (!pFFirst->Path[0])
  1094.         {
  1095.             /* !fDebug ? 0 : printf ("isRoot = TRUE\n"); */
  1096.             isRoot = TRUE;
  1097.         }
  1098.     }
  1099.  
  1100.     if (!(pFFirstAck->rc = MakeNativePath (pFFirst->Path, NATIVEPath, pFFirst->ulAttrib)))
  1101.     {
  1102.         if (!pSearchPattern)
  1103.         {
  1104.             /* The last path element is a file/directory with no wildcards. 
  1105.             Just do a stat on it and return the results */
  1106.  
  1107.             /* !fDebug ? 0 : printf ("FF on single file: %s\n", NATIVEPath); */
  1108.  
  1109.             pffInfo    = (fs_findfileinfo *)((char *)&pFFirstAck->FindFiles);
  1110.  
  1111.             if (!(pFFirstAck->rc = FillFileStatus (NATIVEPath, pffInfo)))
  1112.             {
  1113.                 pFFirstAck->sNumberOfFiles = 1;
  1114.  
  1115.                 /* !fDebug ? 0 : printf ("NATIVEPath = %s\n", NATIVEPath); */
  1116.  
  1117.                 if (pFile = StripFileFromPath (NATIVEPath, NativeSlash))
  1118.                 {
  1119.                     pffInfo->sFileNameLen = strlen(pFile) + 1;
  1120.                     strcpy (pffInfo->FileName, pFile);
  1121.                 }
  1122.  
  1123.                 pFFirstAck->ulRetBufLen = (sizeof(fs_findfileinfo) + 
  1124.                     pffInfo->sFileNameLen - sizeof(pffInfo->FileName));
  1125.  
  1126.                 pffInfo->sFileNameLen = htons(pffInfo->sFileNameLen);
  1127.  
  1128.                 /* !fDebug ? 0 : printf ("pFile = %s\n", pFile); */
  1129.  
  1130.                 pFFirstAck->rc = ERROR_NO_MORE_FILES;
  1131.             }
  1132.             else
  1133.                 pFFirstAck->rc = ERROR_FILE_NOT_FOUND;
  1134.         }
  1135.         else if (pDir = opendir (NATIVEPath))
  1136.         {
  1137.             /* Open the directory and return the handle to Windows */
  1138.  
  1139.             while (pFFirst->ulRetBufLen - (MAX_PATH + 1) >= pFFirstAck->ulRetBufLen)
  1140.             {
  1141.                 /* Get as many files as our buffer size will allow */
  1142.  
  1143.                 pffInfo    = (fs_findfileinfo *)(((char *)&pFFirstAck->FindFiles) + pFFirstAck->ulRetBufLen);
  1144.  
  1145.                 if (!(pFFirstAck->rc = (short)ReadDirEntry (pDir, 
  1146.                     pffInfo, 
  1147.                     NATIVEPath,
  1148.                     pSearchPattern,
  1149.                     isRoot)))
  1150.                 {
  1151.                     pFFirstAck->sNumberOfFiles++;
  1152.  
  1153.                     pFFirstAck->ulRetBufLen += sizeof(fs_findfileinfo) + 
  1154.                         pffInfo->sFileNameLen - sizeof(pffInfo->FileName); 
  1155.  
  1156.                     pffInfo->sFileNameLen = htons(pffInfo->sFileNameLen);
  1157.                 }
  1158.                 else if (pFFirstAck->rc != ERROR_FILE_NOT_FOUND)
  1159.                     break;
  1160.             }
  1161.         }
  1162.         else
  1163.         {
  1164.             !fDebug ? 0 : printf ("Can't find/open file/directory - Path = %s\n", NATIVEPath);
  1165.             pFFirstAck->rc = MapWindowsError (errno);
  1166.         }
  1167.     }
  1168.  
  1169.     pFFirstAck->iFindContext = (int)pDir;
  1170.  
  1171.     /* Write the Ack struct to Windows. We subtract the length of the array
  1172.     already included in fs_findfileinfo */
  1173.  
  1174.     usWriteLen = sizeof(fs_findfirstfileAck) + pFFirstAck->ulRetBufLen;
  1175.  
  1176.     pFFirstAck->usLen = htons(usWriteLen);
  1177.  
  1178.     pFFirstAck->ulKey = pFFirst->ulKey;
  1179.     pFFirstAck->usType = htons(pFFirst->usType);
  1180.  
  1181.     pFFirstAck->rc = htons(pFFirstAck->rc);
  1182.     pFFirstAck->sNumberOfFiles = htons(pFFirstAck->sNumberOfFiles);
  1183.     pFFirstAck->ulRetBufLen = htonl(pFFirstAck->ulRetBufLen);
  1184.  
  1185.     writen (sockfd, pFFirstAck, usWriteLen); 
  1186.  
  1187.     !fDebug ? 0 : printf ("FS_FINDFIRSTFILE: rc=%d, FilesFound=%d\n",
  1188.         ntohs(pFFirstAck->rc),
  1189.         ntohs(pFFirstAck->sNumberOfFiles));
  1190. }
  1191.  
  1192.  
  1193. /*
  1194. *  fsFindNextFile
  1195. */
  1196. void fsFindNextFile (sockfd, pInBuff)
  1197. int sockfd;
  1198. char *pInBuff;
  1199. {
  1200.     fs_findnextfile        *pFNext;
  1201.     fs_findnextfileAck    *pFNextAck;
  1202.     fs_findfileinfo        *pffInfo;
  1203.     char                *pSearchPattern=0;
  1204.     int                    isRoot=FALSE;
  1205.     char                NATIVEPath[MAX_PATH + 1];
  1206.     USHORT                usWriteLen;
  1207.  
  1208.     pFNext = (fs_findnextfile *)pInBuff;
  1209.  
  1210.     pFNext->ulRetBufLen = ntohl(pFNext->ulRetBufLen);
  1211.     pFNext->sPathLen = ntohs(pFNext->sPathLen);
  1212.     pFNext->ulFlags &= ~FILE_FLAG_KEEP_CASE;
  1213.  
  1214.     !fDebug ? 0 : printf ("FS_FINDNEXTFILE: Flags=%x, SearchHandle=%d, BuffLen=%d, Path=%s\n",
  1215.         pFNext->ulFlags, pFNext->iFindHandle, pFNext->ulRetBufLen, pFNext->Path);
  1216.  
  1217.     pFNextAck = (fs_findnextfileAck *)OutBuff;
  1218.     memset ((char *)pFNextAck, 0, sizeof(fs_findnextfileAck));
  1219.  
  1220.     if (pFNext->ulFlags & FILE_FLAG_WILDCARDS || pFNext->ulFlags & FILE_FLAG_HAS_STAR)
  1221.     {
  1222.         /* This is a search pattern - strip it */
  1223.  
  1224.         /* !fDebug ? 0 : printf ("Found wildcard chars\n"); */
  1225.  
  1226.         pSearchPattern = StripFileFromPath (pFNext->Path, WindowsBSlash);
  1227.  
  1228.         if (!pFNext->Path[0])
  1229.             isRoot = TRUE;
  1230.     }
  1231.  
  1232.     if (!(pFNextAck->rc = MakeNativePath (pFNext->Path, NATIVEPath, pFNext->ulFlags)))
  1233.     {
  1234.         while (pFNext->ulRetBufLen - (MAX_PATH + 1) >= pFNextAck->ulRetBufLen)
  1235.         {
  1236.             /* Get as many files as our buffer size will allow */
  1237.  
  1238.             pffInfo    = (fs_findfileinfo *)(((char *)&pFNextAck->FindFiles) + pFNextAck->ulRetBufLen);
  1239.  
  1240.             if (!(pFNextAck->rc = (short)ReadDirEntry ((DIR *)pFNext->iFindHandle,
  1241.                 pffInfo, 
  1242.                 NATIVEPath,
  1243.                 pSearchPattern,
  1244.                 isRoot)))
  1245.             {
  1246.                 pFNextAck->sNumberOfFiles++;
  1247.  
  1248.                 pFNextAck->ulRetBufLen += (sizeof(fs_findfileinfo) + 
  1249.                     pffInfo->sFileNameLen - sizeof(pffInfo->FileName));
  1250.  
  1251.                 pffInfo->sFileNameLen = htons(pffInfo->sFileNameLen);
  1252.             }
  1253.             else
  1254.                 break;
  1255.         }
  1256.     }
  1257.     else
  1258.         pFNextAck->rc = ERROR_NO_MORE_FILES;
  1259.  
  1260.     usWriteLen = sizeof(fs_findnextfileAck) + pFNextAck->ulRetBufLen;
  1261.  
  1262.     pFNextAck->usLen = htons(usWriteLen);
  1263.     pFNextAck->ulKey = pFNext->ulKey;
  1264.     pFNextAck->usType = htons(pFNext->usType);
  1265.  
  1266.     pFNextAck->rc = htons(pFNextAck->rc);
  1267.     pFNextAck->sNumberOfFiles = htons(pFNextAck->sNumberOfFiles);
  1268.     pFNextAck->ulRetBufLen = htonl(pFNextAck->ulRetBufLen);
  1269.  
  1270.     writen (sockfd, pFNextAck, usWriteLen);
  1271.  
  1272.     !fDebug ? 0 : printf ("FS_FINDNEXTFILE: rc=%d, FilesFound=%d\n",
  1273.         ntohs(pFNextAck->rc),
  1274.         ntohs(pFNextAck->sNumberOfFiles));
  1275. }
  1276.  
  1277.  
  1278. /*
  1279. *  ReadDirEntry
  1280. */
  1281. int ReadDirEntry (pDir, pFFileInfo, pPath, pSearchPattern, isRoot)
  1282. DIR    *pDir;
  1283. fs_findfileinfo    *pFFileInfo;
  1284. char *pPath;
  1285. char *pSearchPattern;
  1286. int isRoot;
  1287. {
  1288.     struct    dirent    *pDirEnt;
  1289.  
  1290.     char    NewPath[MAX_PATH];
  1291.     int        fMatched = TRUE, rc, len;
  1292.  
  1293.     isRoot = TRUE;
  1294.  
  1295.     memset ((char *)pFFileInfo, 0, sizeof(fs_findfileinfo));
  1296.  
  1297.     if (pDirEnt = readdir (pDir))
  1298.     {
  1299.         if (isRoot && (!strncmp(pDirEnt->d_name, ".", 1) || !strncmp(pDirEnt->d_name, "..", 2)))
  1300.             fMatched = FALSE;
  1301.         else if (pSearchPattern)
  1302.             fMatched = MetaMatch (pSearchPattern, pDirEnt->d_name);
  1303.  
  1304.         if (fMatched)
  1305.         {
  1306.             len = strlen(pDirEnt->d_name) + 1;  /* Add one for the NULL */
  1307.  
  1308.             /* Pad to 4 byte boundries for pointer alignment sensitive machines */
  1309.  
  1310.             len += 4 - len%4;
  1311.  
  1312.             pFFileInfo->sFileNameLen = len;
  1313.  
  1314.             /*
  1315.             printf("pFFileInfo->sFileNameLen=%d\n", pFFileInfo->sFileNameLen);
  1316.             fflush(stdout);
  1317.             */
  1318.  
  1319.             strcpy (pFFileInfo->FileName, pDirEnt->d_name);
  1320.  
  1321.             strcpy (NewPath, pPath);
  1322.  
  1323.             if (strcmp(NewPath, "/"))
  1324.                 strcat (NewPath, "/");
  1325.  
  1326.             strcat (NewPath, pDirEnt->d_name);
  1327.  
  1328.             /*
  1329.             !fDebug ? 0 : printf ("Found file - pattern=%s, name=%s, NewPath=%s\n", 
  1330.                 pSearchPattern, pDirEnt->d_name, NewPath);
  1331.             fflush(stdout);
  1332.             */
  1333.  
  1334.             if (rc = FillFileStatus (NewPath, pFFileInfo))
  1335.                 return rc;
  1336.         }
  1337.         else
  1338.         {
  1339.             return ERROR_FILE_NOT_FOUND;
  1340.         }
  1341.     }
  1342.     else
  1343.     {
  1344.         /* !fDebug ? 0 : printf ("readdir failed - handle = %d\n", pDir); */
  1345.         return ERROR_NO_MORE_FILES;
  1346.     }
  1347.  
  1348.     return 0;
  1349. }
  1350.  
  1351. /*
  1352. *  FillFileStatus
  1353. */
  1354. int FillFileStatus (pPath, pFFInfo)
  1355. char *pPath;
  1356. fs_findfileinfo    *pFFInfo;
  1357. {
  1358.     struct    stat    fStat;
  1359.  
  1360.     if (!(stat (pPath, &fStat)))
  1361.     {
  1362.         /* !fDebug ? 0 : printf ("stat on %s\n", pPath); */
  1363.  
  1364.         pFFInfo->ulAttrib = 0;
  1365.  
  1366.         if (fStat.st_mode & S_IRUSR && !(fStat.st_mode & S_IWUSR))
  1367.             pFFInfo->ulAttrib |= FILE_ATTRIBUTE_READONLY;
  1368.  
  1369.         if (S_ISDIR(fStat.st_mode))
  1370.         {
  1371.             pFFInfo->ulAttrib |= FILE_ATTRIBUTE_DIRECTORY;
  1372.         }
  1373.  
  1374.         pFFInfo->ulAttrib = htonl(pFFInfo->ulAttrib);
  1375.  
  1376.         pFFInfo->tCreate = htonl(fStat.st_mtime);
  1377.  
  1378.         pFFInfo->tLastAccess = htonl(fStat.st_atime);
  1379.         pFFInfo->tLastWrite = htonl(fStat.st_mtime);
  1380.         pFFInfo->ulFileSize = htonl(fStat.st_size);
  1381.     }
  1382.     else
  1383.     {
  1384.         !fDebug ? 0 : printf ("stat failed on %s\n", pPath);
  1385.         fflush(stdout);
  1386.         return MapWindowsError (errno);
  1387.     }
  1388.  
  1389.     return 0;
  1390. }
  1391.  
  1392.  
  1393. /*
  1394. *  fsFindClose
  1395. */
  1396. void fsFindClose (sockfd, pInBuff)
  1397. int sockfd;
  1398. char *pInBuff;
  1399. {
  1400.     fs_findclose        *pFindClose;
  1401.     fs_findcloseAck        *pFindCloseAck;
  1402.  
  1403.     pFindClose = (fs_findclose *)pInBuff;
  1404.  
  1405.     !fDebug ? 0 : printf ("FS_FINDCLOSE: Handle=%d\n", pFindClose->iFindHandle);
  1406.  
  1407.     pFindCloseAck = (fs_findcloseAck *)OutBuff;
  1408.     memset ((char *)pFindCloseAck, 0, sizeof(fs_findcloseAck));
  1409.     
  1410.     /* No find handle for single file finds */
  1411.  
  1412.     if (pFindClose->iFindHandle)
  1413.         if (closedir ((DIR *)pFindClose->iFindHandle) < 0)
  1414.             pFindCloseAck->rc = htons(MapWindowsError(errno));
  1415.  
  1416.     pFindCloseAck->usLen = htons(sizeof(fs_findcloseAck));
  1417.     pFindCloseAck->ulKey = pFindClose->ulKey;
  1418.     pFindCloseAck->usType = htons(pFindClose->usType);
  1419.  
  1420.     writen (sockfd, pFindCloseAck, sizeof(fs_findcloseAck));
  1421.  
  1422.     !fDebug ? 0 : printf ("FS_FINDCLOSE: rc=%d\n", ntohs(pFindCloseAck->rc));
  1423. }
  1424.  
  1425.  
  1426. /*
  1427. * fsFileAttributes
  1428. */
  1429. void fsFileAttributes (sockfd, pInBuff)
  1430. int sockfd;
  1431. char *pInBuff;
  1432. {
  1433.     fs_fileattributes        *pFileAttrib;
  1434.     fs_fileattributesAck    *pFileAttribAck;
  1435.     struct stat                fStat;
  1436.     struct utimbuf            uTime;
  1437.     char                    NATIVEPath[MAX_PATH + 1];
  1438.  
  1439.     pFileAttrib = (fs_fileattributes *)pInBuff;
  1440.  
  1441.     pFileAttrib->ulAttribs = ntohl(pFileAttrib->ulAttribs);
  1442.     pFileAttrib->NativeTime = ntohl(pFileAttrib->NativeTime);
  1443.     pFileAttrib->sPathLen = ntohs(pFileAttrib->sPathLen);
  1444.  
  1445.     !fDebug ? 0 : printf ("FS_FILEATTRIBUTES: Flags=%x, Attribs=%x, Time=%x, Path=%s\n",
  1446.         pFileAttrib->ulFlags, pFileAttrib->ulAttribs, pFileAttrib->NativeTime, pFileAttrib->Path);
  1447.  
  1448.     pFileAttribAck = (fs_fileattributesAck *)OutBuff;
  1449.     memset ((char *)pFileAttribAck, 0, sizeof(fs_fileattributesAck));
  1450.  
  1451.     if (pFileAttribAck->rc = MakeNativePath (pFileAttrib->Path, NATIVEPath, pFileAttrib->ulAttribs))
  1452.     {}
  1453.     else if (!(pFileAttribAck->rc = stat(NATIVEPath, &fStat)))
  1454.     {
  1455.         uTime.actime = fStat.st_atime;
  1456.         uTime.modtime = fStat.st_mtime;
  1457.                                      
  1458.         /* What does windows want us to do? */
  1459.  
  1460.         switch (pFileAttrib->ulFlags)
  1461.         {
  1462.         case GET_ATTRIBUTES:
  1463.         {
  1464.             !fDebug ? 0 : printf ("GET_ATTRIBUTES - mode=%o\n", fStat.st_mode); 
  1465.  
  1466.             if (S_ISDIR(fStat.st_mode))
  1467.                 pFileAttribAck->ulAttribs |= FILE_ATTRIBUTE_DIRECTORY;
  1468.  
  1469.               if ((fStat.st_mode & S_IRUSR) && !(fStat.st_mode & S_IWUSR))
  1470.                 pFileAttribAck->ulAttribs |= FILE_ATTRIBUTE_READONLY;
  1471.  
  1472.             break;
  1473.         }
  1474.         case SET_ATTRIBUTES:
  1475.         {
  1476.             mode_t mode;
  1477.  
  1478.             !fDebug ? 0 : printf ("SET_ATTRIBUTES - mode=%o\n", fStat.st_mode); 
  1479.  
  1480.             if (pFileAttrib->ulAttribs & FILE_ATTRIBUTE_READONLY)
  1481.                 mode = ulDefaultAttributes & ~(S_IWUSR | S_IWGRP | S_IWOTH);
  1482.             else
  1483.                 mode = ulDefaultAttributes;
  1484.  
  1485.             if (chmod (NATIVEPath, mode) < 0)
  1486.                 pFileAttribAck->rc = MapWindowsError (errno);
  1487.  
  1488.             break;
  1489.         }
  1490.         case GET_ATTRIB_COMP_FILESIZE:
  1491.         {
  1492.             !fDebug ? 0 : printf ("GET_ATTRIB_COMP_FILESIZE\n"); 
  1493.             pFileAttribAck->ulFileSize = fStat.st_size;
  1494.             break;
  1495.         }
  1496.         case GET_ATTRIB_MODIFY_DATETIME:
  1497.         {
  1498.             !fDebug ? 0 : printf ("GET_ATTRIB_MODIFY_DATETIME\n"); 
  1499.             pFileAttribAck->NativeTime = fStat.st_mtime;
  1500.             break;
  1501.         }
  1502.         case SET_ATTRIB_MODIFY_DATETIME:
  1503.         {
  1504.             !fDebug ? 0 : printf ("SET_ATTRIB_MODIFY_DATETIME\n"); 
  1505.             uTime.modtime = pFileAttrib->NativeTime;
  1506.  
  1507.             if (utime (NATIVEPath, &uTime) < 0)
  1508.                 pFileAttribAck->rc = MapWindowsError (errno);
  1509.  
  1510.             break;
  1511.         }
  1512.         case GET_ATTRIB_LAST_ACCESS_DATETIME:
  1513.         {    
  1514.             !fDebug ? 0 : printf ("GET_ATTRIB_LAST_ACCESS_DATETIME\n"); 
  1515.             pFileAttribAck->NativeTime = fStat.st_atime;
  1516.             break;
  1517.         }
  1518.         case SET_ATTRIB_LAST_ACCESS_DATETIME:
  1519.         {
  1520.             !fDebug ? 0 : printf ("SET_ATTRIB_LAST_ACCESS_DATETIME\n");
  1521.             uTime.actime = pFileAttrib->NativeTime;
  1522.  
  1523.             if (utime (NATIVEPath, &uTime) < 0)
  1524.                 pFileAttribAck->rc = MapWindowsError (errno);
  1525.  
  1526.             break;
  1527.         }
  1528.         case GET_ATTRIB_CREATION_DATETIME:
  1529.         {
  1530.             !fDebug ? 0 : printf ("GET_ATTRIB_CREATION_DATETIME\n"); 
  1531.             pFileAttribAck->NativeTime = fStat.st_mtime;
  1532.             break;
  1533.         }
  1534.         case SET_ATTRIB_CREATION_DATETIME:
  1535.         {
  1536.             !fDebug ? 0 : printf ("SET_ATTRIB_CREATION_DATETIME\n"); 
  1537.             uTime.modtime = pFileAttrib->NativeTime;
  1538.  
  1539.             if (utime (NATIVEPath, &uTime) < 0)
  1540.                 pFileAttribAck->rc = MapWindowsError (errno);
  1541.  
  1542.             break;
  1543.         }
  1544.         default:
  1545.             !fDebug ? 0 : printf ("File Attributes: ERROR! Unknown Type=%d\n", pFileAttrib->ulFlags);
  1546.         }
  1547.     }
  1548.     else
  1549.     {
  1550.         pFileAttribAck->rc = MapWindowsError (errno);
  1551.         !fDebug ? 0 : printf ("fsFileAttributes: Stat failed on %s\n", NATIVEPath);
  1552.     }
  1553.  
  1554.     pFileAttribAck->usLen = htons(sizeof(fs_fileattributesAck));
  1555.     pFileAttribAck->ulKey = pFileAttrib->ulKey;
  1556.     pFileAttribAck->usType = htons(pFileAttrib->usType);
  1557.  
  1558.     pFileAttribAck->ulAttribs = htonl(pFileAttribAck->ulAttribs);
  1559.     pFileAttribAck->NativeTime = htonl(pFileAttribAck->NativeTime);
  1560.     pFileAttribAck->ulFileSize = htonl(pFileAttribAck->ulFileSize);
  1561.     pFileAttribAck->rc = htons(pFileAttribAck->rc);
  1562.  
  1563.     writen (sockfd, pFileAttribAck, sizeof(fs_fileattributesAck));
  1564.  
  1565.     !fDebug ? 0 : printf ("FS_FILEATTRIBUTES: rc=%d, attrib=%x\n", 
  1566.         ntohs(pFileAttribAck->rc), ntohl(pFileAttribAck->ulAttribs));
  1567. }
  1568.  
  1569.  
  1570. /*
  1571. *  fsDir
  1572. */
  1573. void fsDir (sockfd, pInBuff)
  1574. int sockfd;
  1575. char *pInBuff;
  1576. {
  1577.     fs_dir        *pDir;
  1578.     fs_dirAck    *pDirAck;
  1579.     struct stat    fStat;
  1580.     char        NATIVEPath[MAX_PATH];
  1581.     ULONG        ulDirAttribs=ulDefaultAttributes;
  1582.  
  1583.     pDir = (fs_dir *)pInBuff;
  1584.  
  1585.     pDir->ulAttribs = ntohl(pDir->ulAttribs);
  1586.     pDir->sPathLen = ntohs(pDir->sPathLen);
  1587.  
  1588.     !fDebug ? 0 : printf ("FS_DIR: Flags=%x, Path=%s\n", pDir->ulFlags, pDir->Path);
  1589.  
  1590.     pDirAck = (fs_dirAck *)OutBuff;
  1591.     memset ((char *)pDirAck, 0, sizeof(fs_dirAck));
  1592.  
  1593.     pDirAck->rc = MakeNativePath (pDir->Path, NATIVEPath, pDir->ulAttribs);
  1594.  
  1595.     if (!pDirAck->rc)
  1596.     {
  1597.         switch (pDir->ulFlags)
  1598.         {
  1599.         case CREATE_DIR:
  1600.         {
  1601.             if (ulDefaultAttributes & S_IRUSR)
  1602.                 ulDirAttribs |= S_IXUSR;
  1603.             if (ulDefaultAttributes & S_IRGRP)
  1604.                 ulDirAttribs |= S_IXGRP;
  1605.             if (ulDefaultAttributes & S_IROTH)
  1606.                 ulDirAttribs |= S_IXOTH;
  1607.             
  1608.             !fDebug ? 0 : printf ("CREATE_DIR: %s\n", NATIVEPath);
  1609.  
  1610.             if (mkdir(NATIVEPath, ulDirAttribs) < 0)
  1611.                 pDirAck->rc = MapWindowsError (errno);
  1612.             break;
  1613.         }
  1614.         case DELETE_DIR:
  1615.         {
  1616.             !fDebug ? 0 : printf ("DELETE_DIR: %s\n", NATIVEPath);
  1617.             if (rmdir(NATIVEPath) < 0)
  1618.                 pDirAck->rc = MapWindowsError (errno);
  1619.             break;
  1620.         }
  1621.         case QUERY83_DIR:
  1622.         {
  1623.             !fDebug ? 0 : printf ("QUERY83_DIR: %s\n", NATIVEPath);
  1624.             pDirAck->rc = ERROR_INVALID_FUNCTION;
  1625.             break;
  1626.         }
  1627.         case QUERYLONG_DIR:
  1628.         {
  1629.             !fDebug ? 0 : printf ("QUERYLONG_DIR: %s\n", NATIVEPath);
  1630.             pDirAck->rc = ERROR_INVALID_FUNCTION;
  1631.             break;
  1632.         }
  1633.         case CHECK_DIR:
  1634.         {
  1635.             !fDebug ? 0 : printf ("CHECK_DIR: %s\n", NATIVEPath);
  1636.  
  1637.             if (!(stat (NATIVEPath, &fStat)))
  1638.             {
  1639.                 if (S_ISDIR(fStat.st_mode))
  1640.                 {
  1641.                     !fDebug ? 0 : printf ("Found Valid Directory\n");
  1642.                     pDirAck->rc = 0;
  1643.                 }
  1644.                 else
  1645.                     pDirAck->rc = ERROR_FILE_NOT_FOUND;
  1646.             }
  1647.             else
  1648.                 pDirAck->rc = MapWindowsError (errno);
  1649.  
  1650.             break;
  1651.         }
  1652.         default:
  1653.             !fDebug ? 0 : printf ("FsDir: ERROR_INVALID_FUNCTION!!!!\n");
  1654.             pDirAck->rc = ERROR_INVALID_FUNCTION;
  1655.         }
  1656.     }
  1657.     else 
  1658.         pDirAck->rc = ERROR_PATH_NOT_FOUND;
  1659.  
  1660.     pDirAck->usLen = htons(sizeof(fs_dirAck));
  1661.     pDirAck->ulKey = pDir->ulKey;
  1662.     pDirAck->usType = htons(pDir->usType);
  1663.  
  1664.     pDirAck->rc = htons(pDirAck->rc);
  1665.  
  1666.     writen (sockfd, pDirAck, sizeof(fs_dirAck));
  1667.  
  1668.     !fDebug ? 0 : printf ("FS_DIR: rc=%d\n", ntohs(pDirAck->rc));
  1669. }
  1670.  
  1671.  
  1672. /*
  1673. *  fsDeleteFile
  1674. */
  1675. void fsDeleteFile (sockfd, pInBuff)
  1676. int sockfd;
  1677. char *pInBuff;
  1678. {
  1679.     fs_deletefile        *pDelete;
  1680.     fs_deletefileAck    *pDeleteAck;
  1681.     DIR                    *pDir;
  1682.     struct    dirent        *pDirEnt = 0;
  1683.     int                    fDeleted=FALSE;
  1684.     char        NATIVEPath[MAX_PATH];
  1685.     char        DeletePath[MAX_PATH];
  1686.     struct stat                fStat;
  1687.  
  1688.     pDelete = (fs_deletefile *)pInBuff;
  1689.  
  1690.     pDelete->sPathLen = ntohs(pDelete->sPathLen);
  1691.  
  1692.     !fDebug ? 0 : printf ("FS_DELETEFILE: Attribs=%x, Path=%s\n", 
  1693.         pDelete->ulAttribs, pDelete->Path);
  1694.  
  1695.     pDeleteAck = (fs_deletefileAck *)OutBuff;
  1696.     memset ((char *)pDeleteAck, 0, sizeof(fs_deletefileAck));
  1697.  
  1698.     if (!(pDeleteAck->rc = MakeNativePath (pDelete->Path, NATIVEPath, pDelete->ulAttribs)))
  1699.     {
  1700.         if (!(stat(NATIVEPath, &fStat)))
  1701.         {
  1702.             if (!(fStat.st_mode & S_IWUSR))
  1703.             {
  1704.                 /* Readonly */
  1705.  
  1706.                 pDeleteAck->rc = ERROR_ACCESS_DENIED;
  1707.             }
  1708.             else if (!S_ISDIR(fStat.st_mode))
  1709.             {
  1710.                 /* Delete a single file */
  1711.  
  1712.                 !fDebug ? 0 : printf ("FS_DELETEFILE: Single file delete\n");
  1713.  
  1714.                 if (unlink(NATIVEPath) < 0)
  1715.                 {
  1716.                     pDeleteAck->rc = MapWindowsError (errno);
  1717.  
  1718.                     !fDebug ? 0 : printf ("FS_DELETEFILE: fail - rc = %d\n", errno);
  1719.                 }
  1720.                 else
  1721.                     pDeleteAck->rc = 0;
  1722.             }
  1723.             else 
  1724.             {
  1725.                 !fDebug ? 0 : printf ("FS_DELETEFILE: Directory delete\n");
  1726.  
  1727.                 /* Delete the whole directory */
  1728.  
  1729.                 if (pDir = opendir (NATIVEPath))
  1730.                 {
  1731.                     while (pDirEnt = readdir (pDir))
  1732.                     {
  1733.                         if (!strncmp(pDirEnt->d_name, ".", 1) || !strncmp(pDirEnt->d_name, "..", 2))
  1734.                             continue;
  1735.  
  1736.                         strcpy (DeletePath, NATIVEPath);
  1737.                         strcat (DeletePath, "/");
  1738.                         strcat (DeletePath, pDirEnt->d_name);
  1739.  
  1740.                         if (unlink(DeletePath) < 0)
  1741.                         {
  1742.                             pDeleteAck->rc = MapWindowsError (errno);
  1743.                             break;
  1744.                         }
  1745.                         else 
  1746.                             fDeleted = TRUE;
  1747.                     }
  1748.                     closedir (pDir);
  1749.  
  1750.                     if (!fDeleted)
  1751.                         pDeleteAck->rc = ERROR_FILE_NOT_FOUND;
  1752.                 }
  1753.                 else 
  1754.                     pDeleteAck->rc = ERROR_FILE_NOT_FOUND;
  1755.             }
  1756.         }
  1757.         else 
  1758.             pDeleteAck->rc = ERROR_FILE_NOT_FOUND;
  1759.     }
  1760.  
  1761.     pDeleteAck->usLen = htons(sizeof(fs_deletefileAck));
  1762.     pDeleteAck->ulKey = pDelete->ulKey;
  1763.     pDeleteAck->usType = htons(pDelete->usType);
  1764.  
  1765.     pDeleteAck->rc = htons(pDeleteAck->rc);
  1766.  
  1767.     writen (sockfd, pDeleteAck, sizeof(fs_deletefileAck));
  1768.  
  1769.     !fDebug ? 0 : printf ("FS_DELETEFILE: rc=%d\n", ntohs(pDeleteAck->rc));
  1770. }
  1771.  
  1772.  
  1773. /*
  1774. *  fsRenameFile
  1775. */
  1776. void fsRenameFile (sockfd, pInBuff)
  1777. int sockfd;
  1778. char *pInBuff;
  1779. {
  1780.     fs_renamefile        *pRename;
  1781.     fs_renamefileAck    *pRenameAck;
  1782.     char                NATIVEPath1[MAX_PATH];
  1783.     char                NATIVEPath2[MAX_PATH];
  1784.  
  1785.     pRename = (fs_renamefile *)pInBuff;
  1786.  
  1787.     pRename->sPathLen1 = ntohs(pRename->sPathLen1);
  1788.     pRename->sPathLen2 = ntohs(pRename->sPathLen2);
  1789.  
  1790.     !fDebug ? 0 : printf ("FS_RENAMEFILE: Attribs=%x, From=%s, To=%s\n",
  1791.         pRename->ulAttribs, pRename->Paths, &pRename->Paths[pRename->sPathLen1]);
  1792.         
  1793.     pRenameAck = (fs_renamefileAck *)OutBuff;
  1794.     memset ((char *)pRenameAck, 0, sizeof(fs_renamefileAck));
  1795.  
  1796.     if (!(pRenameAck->rc = MakeNativePath (pRename->Paths, NATIVEPath1, 0)))
  1797.     {
  1798.         pRenameAck->rc = MakeNativePath (&pRename->Paths[pRename->sPathLen1], NATIVEPath2, pRename->ulAttribs);
  1799.  
  1800.         if (!pRenameAck->rc)
  1801.         {
  1802.             if (rename(NATIVEPath1, NATIVEPath2) < 0)
  1803.                 pRenameAck->rc = MapWindowsError (errno);
  1804.         }
  1805.     }
  1806.     else
  1807.         pRenameAck->rc = ERROR_PATH_NOT_FOUND;
  1808.  
  1809.     pRenameAck->usLen = htons(sizeof(fs_renamefileAck));
  1810.     pRenameAck->ulKey = pRename->ulKey;
  1811.     pRenameAck->usType = htons(pRename->usType);
  1812.  
  1813.     pRenameAck->rc = htons(pRenameAck->rc);
  1814.  
  1815.     writen (sockfd, pRenameAck, sizeof(fs_renamefileAck));
  1816.  
  1817.     !fDebug ? 0 : printf ("FS_RENAMEFILE: rc=%d\n", ntohs(pRenameAck->rc));
  1818. }
  1819.  
  1820.  
  1821. /*
  1822. *  fsGetDiskInfo
  1823. */
  1824. void fsGetDiskInfo (sockfd, pInBuff)
  1825. int sockfd;
  1826. char *pInBuff;
  1827. {
  1828.     fs_getdiskinfo        *pGetDiskInfo;
  1829.     fs_getdiskinfoAck    *pGetDiskInfoAck;
  1830.     ULONG                ulFileCount=0;
  1831.  
  1832.     /* Walk the tree starting from the directory where we were
  1833.        started and not exceeding MAX readdir count */
  1834.  
  1835.     pGetDiskInfo = (fs_getdiskinfo *)pInBuff;
  1836.  
  1837.     !fDebug ? 0 : printf ("FS_GETDISKINFO: Starting Tree Walk...\n");
  1838.  
  1839.     pGetDiskInfoAck = (fs_getdiskinfoAck *)OutBuff;
  1840.     memset ((char *)pGetDiskInfoAck, 0, sizeof(fs_getdiskinfoAck));
  1841.  
  1842.     ProcessDir (HomePath, &pGetDiskInfoAck->ulDiskSpaceUsedBytes, &ulFileCount);
  1843.  
  1844.     if (ulFileCount >= ulMaxReaddirs)
  1845.         pGetDiskInfoAck->ulDiskSpaceUsedBytes = 0;
  1846.  
  1847.     pGetDiskInfoAck->usLen = htons(sizeof(fs_getdiskinfoAck));
  1848.     pGetDiskInfoAck->ulKey = pGetDiskInfo->ulKey;
  1849.     pGetDiskInfoAck->usType = htons(pGetDiskInfo->usType);
  1850.  
  1851.     pGetDiskInfoAck->ulDiskSpaceUsedBytes = htonl(pGetDiskInfoAck->ulDiskSpaceUsedBytes);
  1852.     pGetDiskInfoAck->rc = htons(pGetDiskInfoAck->rc);
  1853.  
  1854.     writen (sockfd, pGetDiskInfoAck, sizeof(fs_getdiskinfoAck));
  1855.  
  1856.     !fDebug ? 0 : printf ("FS_GETDISKINFO: rc=%d, DiskSize=%d\n", 
  1857.         ntohs(pGetDiskInfoAck->rc),
  1858.         ntohl(pGetDiskInfoAck->ulDiskSpaceUsedBytes));
  1859. }
  1860.  
  1861.  
  1862.  
  1863. /*
  1864. *  ProcessDir
  1865. */
  1866. void ProcessDir (pPath, pulDiskSpace, pulFileCount)
  1867. char *pPath;
  1868. ULONG *pulDiskSpace;
  1869. ULONG *pulFileCount;
  1870. {
  1871.     DIR                    *pCurrDir;
  1872.     struct    dirent        *pDirEntry;
  1873.     struct    stat        Status;
  1874.     char                Cwd[MAX_PATH];
  1875.  
  1876.     if (pCurrDir = opendir (pPath))
  1877.     {
  1878.         if (getcwd (Cwd,MAX_PATH))
  1879.         {
  1880.             if (!chdir(pPath))
  1881.             {
  1882.                 while (pDirEntry = readdir (pCurrDir))
  1883.                 {
  1884.                     if (!stat(pDirEntry->d_name, &Status))
  1885.                     {
  1886.                         *pulDiskSpace += Status.st_size;
  1887.                         (*pulFileCount)++;
  1888.     
  1889.                         /*
  1890.                             !fDebug ? 0 : printf ("ProcessDir: File=%s, Total Size=%d, Count=%d\n",
  1891.                                 pDirEntry->d_name, *pulDiskSpace, *pulFileCount);
  1892.                         */
  1893.  
  1894.                         if (*pulFileCount >= ulMaxReaddirs)
  1895.                             break;
  1896.                                 
  1897.                         if (strcmp(pDirEntry->d_name, "."))
  1898.                         {
  1899.                             if (strcmp(pDirEntry->d_name, ".."))
  1900.                             {
  1901.                                 if (S_ISDIR(Status.st_mode))
  1902.                                 {
  1903.                                     ProcessDir (pDirEntry->d_name, pulDiskSpace, pulFileCount);
  1904.                                 }
  1905.                             }
  1906.                         }
  1907.                     }
  1908.                 }
  1909.             }
  1910.             chdir (Cwd);
  1911.         }
  1912.         closedir (pCurrDir);
  1913.     }
  1914. }
  1915.  
  1916.  
  1917. /*****************************************************
  1918.  
  1919.   UTILITIES
  1920.  
  1921. ******************************************************/
  1922.  
  1923. /*
  1924. * MakeNativePath  
  1925. */
  1926. int MakeNativePath (pInPath, pOutPath, ulAttrib)
  1927. char *pInPath;
  1928. char *pOutPath;
  1929. ULONG ulAttrib;
  1930. {
  1931.     char    *p;
  1932.     int        i, rc=0;
  1933.     char    TempInPath[MAX_PATH];
  1934.     char    TempOutPath[MAX_PATH];
  1935.     char    LastElement[MAX_PATH];
  1936.     char    *pLastElement;
  1937.  
  1938.     /* !fDebug ? 0 : printf ("MakeNativePath - InPath = %s\n", pInPath); */ 
  1939.  
  1940.     if (!pInPath)
  1941.         return 0;
  1942.  
  1943.     if (!pInPath[0])
  1944.     {
  1945.         strcpy (pOutPath, HomePath);      
  1946.         return 0;
  1947.     }
  1948.     if (ulAttrib & FILE_FLAG_KEEP_CASE)
  1949.     {
  1950.         !fDebug ? 0 : printf ("MakeNativePath - FILE_FLAG_KEEP_CASE set\n"); 
  1951.  
  1952.         /* If we are keeping the last element case sensitive, there is
  1953.         no need to map it to the server. Strip it now and add back later */
  1954.  
  1955.         if (pLastElement = StripFileFromPath (pInPath, WindowsBSlash))
  1956.             strcpy (LastElement, pLastElement);
  1957.         else
  1958.             LastElement[0] = 0;
  1959.     }
  1960.  
  1961.     strcpy (TempOutPath, HomePath);
  1962.  
  1963.     if (pInPath[0])
  1964.     {
  1965.         /* Convert all the '\' to '/' */
  1966.  
  1967.         for (i=0, p=pInPath; i<strlen(pInPath); i++, p++)
  1968.         {
  1969.             if (*p == WindowsBSlash)
  1970.                 *p = NativeSlash;
  1971.         }
  1972.  
  1973.         strcpy (TempInPath, pInPath);
  1974.     
  1975.         /* Parse the path (if any) and make sure we can find 
  1976.         all the sub-dirs in UPPERCASE for Windows  */
  1977.  
  1978.         if (p = strtok (TempInPath, NativeSlashStr))
  1979.         {
  1980.             if (!(rc = CaseMatchDirectory (p, TempOutPath)))
  1981.             {
  1982.                 /* !fDebug ? 0 : printf ("MakeNativePath - adding: %s\n", TempOutPath); */ 
  1983.  
  1984.                 while (p = strtok (NULL, NativeSlashStr))
  1985.                 {
  1986.                     if (rc = CaseMatchDirectory (p, TempOutPath))
  1987.                         break;
  1988.                     
  1989.                     /* !fDebug ? 0 : printf ("MakeNativePath - adding: %s\n", TempOutPath); */
  1990.                 }
  1991.             }
  1992.         }
  1993.     }
  1994.  
  1995.     strcpy (pOutPath, TempOutPath);
  1996.  
  1997.     /* Put back any case sensitive elements */
  1998.  
  1999.     if (ulAttrib & FILE_FLAG_KEEP_CASE)
  2000.     {
  2001.         if (LastElement[0])
  2002.         {
  2003.             if (strcmp(pOutPath, "/"))
  2004.                 strcat (pOutPath, "/");
  2005.  
  2006.             strcat (pOutPath, LastElement);
  2007.         }
  2008.     }
  2009.  
  2010.     /* !fDebug ? 0 : printf ("MakeNativePath - OutPath = %s\n", pOutPath); */ 
  2011.  
  2012.     return rc;
  2013. }
  2014.  
  2015.  
  2016. /*
  2017. *  CaseMatchDirectory
  2018. */
  2019. int CaseMatchDirectory (pFile, pPath)
  2020. char *pFile;
  2021. char *pPath;
  2022. {
  2023.     DIR                *pDir;
  2024.     struct    dirent    *pDirEnt = 0;
  2025.     char            TempFile[MAX_PATH];
  2026.  
  2027.     if (pDir = opendir (pPath))
  2028.     {
  2029.         while (pDirEnt = readdir (pDir))
  2030.         {
  2031.             strcpy (TempFile, pDirEnt->d_name);
  2032.  
  2033.             if (!(strcmp(zstrupr(pFile), zstrupr(TempFile))))
  2034.             {
  2035.                 /* We found the directory/file. Add it to path */
  2036.  
  2037.                 if (strcmp(pPath, "/"))
  2038.                     strcat (pPath, "/");
  2039.  
  2040.                 /* !fDebug ? 0 : printf ("CaseMatchDirectory: Found = %s\n", pDirEnt->d_name); */ 
  2041.  
  2042.                 strcat (pPath, pDirEnt->d_name);
  2043.                 closedir (pDir);
  2044.  
  2045.                 return 0;
  2046.             }
  2047.         }
  2048.     }
  2049.     else
  2050.     {
  2051.         !fDebug ? 0 : printf ("CaseMatchDirectory - Can't open dir: %s, File: %s\n", pPath, pFile);
  2052.         return MapWindowsError (errno);
  2053.     }
  2054.  
  2055.     closedir (pDir);
  2056.     return ERROR_FILE_NOT_FOUND;
  2057. }
  2058.  
  2059.  
  2060. /*
  2061. *  zstrupr
  2062. */
  2063. char *zstrupr (pString)
  2064. char *pString;
  2065. {
  2066.     char    *p = pString;
  2067.  
  2068.     while (*p)
  2069.     {
  2070.         if (*p >= 'a' && *p <= 'z')
  2071.             *p -= 32;
  2072.  
  2073.         p++;
  2074.     }
  2075.     return pString;
  2076. }
  2077.  
  2078.  
  2079. #define        STAR_DOT_STAR    "*.*"
  2080. #define        STAR_DOT        "*."
  2081. #define        LONE_STAR        "*"
  2082.  
  2083. /*
  2084. * MetaMatch - Warning! You must convert to a native path before using this routine.
  2085. *             Also, you don't need to call this routine unless the FILE_FLAG_HAS_STAR
  2086. *             flag is set in the FS_FINDFIRSTFILE, FS_RENAMEFILE, and FS_DELETEFILE
  2087. *             file system calls.
  2088. *
  2089. * Note: Even with long filenames Windows 95 still supports "*.*" and "*." in 
  2090. *       the old 8.3 fashion. 
  2091. *
  2092. *  
  2093. */
  2094. int MetaMatch (pWindowsFile, pNativeFile)
  2095. char *pWindowsFile;
  2096. char *pNativeFile;
  2097. {
  2098.     char    tmpWindowsPattern[MAX_PATH];
  2099.     char    tmpNativeFile[MAX_PATH];
  2100.  
  2101.     int        rc;
  2102.  
  2103.     /* In Windows long file name support the meta-character '*' indicates
  2104.     0 or more characters and '?' indicates one character. You can have
  2105.     multiple '*' and '?' */
  2106.  
  2107.     /* printf ("MetaMatch File=%s, Path=%s\n", pWindowsFile, pNativeFile); */  
  2108.  
  2109.     if (pWindowsFile[0] == 0)
  2110.         return FALSE;
  2111.  
  2112.     strcpy (tmpWindowsPattern, pWindowsFile);
  2113.     strcpy (tmpNativeFile, pNativeFile);
  2114.  
  2115.     zstrupr (tmpWindowsPattern);
  2116.     zstrupr (tmpNativeFile);
  2117.  
  2118.     /* No path names at this point */
  2119.  
  2120.     if (strrchr (tmpWindowsPattern, NativeSlash))
  2121.         return FALSE;
  2122.  
  2123.     /* Handle special Windows case: "*.*", "*." and regular "*" */
  2124.  
  2125.     if (!(strcmp(tmpWindowsPattern, LONE_STAR)))
  2126.         return TRUE;    /* This was a "*" */
  2127.  
  2128.     if (!(strcmp(tmpWindowsPattern, STAR_DOT_STAR)))
  2129.         return TRUE;    /* This was a "*.*" */
  2130.  
  2131.     rc = CheckForExtension (pNativeFile);
  2132.  
  2133.     if (!(strcmp(tmpWindowsPattern, STAR_DOT)))
  2134.         return     rc ? FALSE : TRUE; /* This was a "*." */
  2135.  
  2136.     if (!rc) /* If no extension */
  2137.     {
  2138.         /* Handle "<pattern>.*" case for files without extensions */
  2139.  
  2140.         NukeDotStar (tmpWindowsPattern);
  2141.     }
  2142.  
  2143.     return MatchStarsAndQMs (tmpWindowsPattern, tmpNativeFile);
  2144. }
  2145.  
  2146.  
  2147. /*
  2148. *  MatchStarsAndQMs
  2149. */
  2150. int MatchStarsAndQMs (pPattern, pNativeFile)
  2151. char *pPattern;
  2152. char *pNativeFile;
  2153. {
  2154.     char *pP=pPattern, *pF=pNativeFile;
  2155.  
  2156.     /*
  2157.     printf ("MatchStarsAndQMs - pPattern=%s, pNativeFile=%s\n", 
  2158.         pPattern, pNativeFile);
  2159.     */
  2160.  
  2161.     while (*pF && *pP) /* Scan through file name */
  2162.     {
  2163.         if (*pP == '?')
  2164.         {
  2165.             pP++; pF++;
  2166.         }
  2167.         else if (*pP == '*')
  2168.         {
  2169.             pP++;
  2170.  
  2171.             if (*pP == 0)
  2172.                 return TRUE;
  2173.  
  2174.             if (*pP == '*')
  2175.             {
  2176.                 pP++;
  2177.  
  2178.                 if (*pP == 0)
  2179.                     return TRUE;
  2180.  
  2181.             }
  2182.             if (!(FindSubPattern (pP, pF, &pP, &pF)))
  2183.                 pP--;
  2184.             else if (*pP == 0 && *pF != 0)
  2185.                 return FALSE;
  2186.         }
  2187.         else if (*pP == *pF)
  2188.         {
  2189.             pP++; pF++;
  2190.         }
  2191.         else if (*pP != *pF)
  2192.         {
  2193.             return FALSE;
  2194.         }
  2195.  
  2196.     }
  2197.     if (*pP)
  2198.         return FALSE;
  2199.     
  2200.     return TRUE;
  2201. }
  2202.  
  2203.  
  2204. /*
  2205. *  FindSubPattern
  2206. */
  2207. int FindSubPattern (pSubPat, pSubFile, pPatOut, pFileOut)
  2208. char *pSubPat;
  2209. char *pSubFile;
  2210. char **pPatOut;
  2211. char **pFileOut;
  2212. {
  2213.     char    *pSubTmp = pSubPat;
  2214.  
  2215.     /* printf ("FindSubPattern - pSubPat=%s, pSubFile=%s\n", pSubPat, pSubFile); */ 
  2216.  
  2217.     while (*pSubPat && *pSubFile)
  2218.     {
  2219.         /* Compare up to next '*' skip any '?' */
  2220.  
  2221.         if (*pSubPat == '*')
  2222.         {
  2223.             *pPatOut = pSubPat;
  2224.             *pFileOut = pSubFile;
  2225.  
  2226.             return TRUE;
  2227.         }
  2228.  
  2229.         if (*pSubPat == '?')
  2230.         {
  2231.             pSubPat++;
  2232.         }
  2233.         else if (*pSubPat == *pSubFile)
  2234.         {
  2235.             pSubPat++;
  2236.         }
  2237.         else
  2238.             pSubPat = pSubTmp;
  2239.  
  2240.         pSubFile++;
  2241.     }
  2242.     *pFileOut = pSubFile;
  2243.  
  2244.     if (*pSubPat == 0 && *pSubFile)
  2245.         return FALSE;
  2246.  
  2247.     if (*pSubPat)
  2248.         return TRUE;
  2249.     
  2250.     *pPatOut = pSubPat;
  2251.  
  2252.     return TRUE;
  2253. }
  2254.  
  2255.  
  2256.  
  2257. /*
  2258. *  CheckForExtension
  2259. */
  2260. int CheckForExtension (pFile)
  2261. char *pFile;
  2262. {
  2263.     char    *p;
  2264.     int        i;
  2265.  
  2266.     /* This was a "*."  If any of the last four characters is a '.'
  2267.     we consider this a file with an 8.3 extenstion. Windows uses
  2268.     "*." to indicate files with no extension. */
  2269.  
  2270.     p = &pFile[strlen(pFile)-1];    /* Last char in string */
  2271.  
  2272.     for (i=0; i<4; i++, p--)
  2273.     {
  2274.         if (*p == '.')
  2275.             return TRUE;
  2276.     }
  2277.  
  2278.     return FALSE;
  2279. }
  2280.  
  2281.  
  2282. /*
  2283. *  NukeDotStar
  2284. */
  2285. void NukeDotStar (pPattern)
  2286. char *pPattern;
  2287. {
  2288.     if (strlen(pPattern) >= 2)
  2289.     {
  2290.         if (pPattern[strlen(pPattern)-1] == '*')
  2291.         {
  2292.             if (pPattern[strlen(pPattern)-2] == '.')
  2293.             {
  2294.                 pPattern[strlen(pPattern)-2] = 0;
  2295.             }
  2296.         }
  2297.     }
  2298. }
  2299.  
  2300.  
  2301. /*
  2302. *  StripFileFromPath - Puts a NULL in the last '\' and return ptr 
  2303. *                      to the file or search.
  2304. */
  2305. char *StripFileFromPath (pPath, SlashType)
  2306. char *pPath;
  2307. char SlashType;
  2308. {
  2309.     char *p;
  2310.  
  2311.     /* Get the file name from the full Windows path. Windows ALWAYS provides
  2312.     a full path starting with '\' */
  2313.  
  2314.     if (!(p = strrchr (pPath, SlashType)))
  2315.         return 0;
  2316.  
  2317.     *p = 0;
  2318.  
  2319.     return p+1;
  2320. }
  2321.     
  2322.  
  2323. /*
  2324. *  Read "n" bytes from a stream socket 
  2325. */
  2326. int readn (fd, ptr, nbytes)
  2327. int fd;
  2328. char *ptr;
  2329. int nbytes;
  2330. {
  2331.     int    nleft, nread;
  2332.  
  2333.     nleft = nbytes;
  2334.  
  2335.     while (nleft > 0)
  2336.     {
  2337.         nread = read (fd, ptr, nleft);
  2338.  
  2339.         if (nread < 0)
  2340.         {
  2341.             !fDebug ? 0 : printf ("%s File Error:  read(), rc = %d\n", ProgramName, nread);
  2342.             return nread;
  2343.         }
  2344.         else if (nread == 0)
  2345.             break;        /* EOF */
  2346.  
  2347.         nleft -= nread;
  2348.         ptr += nread;
  2349.     }
  2350.     return (nbytes - nleft);    /* return >= 0 */
  2351. }
  2352.  
  2353.  
  2354. /*
  2355. *  Write "n" bytes to a stream socket 
  2356. */
  2357. int writen (fd, ptr, nbytes)
  2358. int fd;
  2359. char *ptr;
  2360. int nbytes;
  2361. {
  2362.     int    nleft, nwritten;
  2363.  
  2364.     nleft = nbytes;
  2365.  
  2366.     while (nleft > 0)
  2367.     {
  2368.         nwritten = write (fd, ptr, nleft);
  2369.  
  2370.         if (nwritten <= 0)            /* error */
  2371.         {
  2372.             !fDebug ? 0 : printf ("%s File Error:  write(), rc = %d\n", ProgramName, nwritten);
  2373.             return nwritten;
  2374.         }
  2375.  
  2376.         nleft -= nwritten;
  2377.         ptr += nwritten;
  2378.     }
  2379.     return (nbytes - nleft);
  2380. }
  2381.  
  2382.  
  2383. /*
  2384. *  MapWindowsError
  2385. */
  2386. USHORT MapWindowsError (usPosixErr)
  2387. USHORT usPosixErr;
  2388. {
  2389.     if (usPosixErr > MAX_ERRORS)
  2390.         return usPosixErr;
  2391.  
  2392.     return WindowsErrors[usPosixErr];
  2393. }
  2394.  
  2395.  
  2396. /*
  2397. *  SetFilePosition
  2398. */
  2399. int SetFilePosition (iFileDesc, lNewPos)
  2400. int iFileDesc;
  2401. long lNewPos;
  2402. {
  2403.     struct stat    fStat;
  2404.     long lPosition;
  2405.  
  2406.     /* Get the length of this file */
  2407.  
  2408.     if (fstat(iFileDesc, &fStat) < 0)
  2409.         return MapWindowsError(errno);
  2410.  
  2411.     /* Make sure we are within the file */
  2412.  
  2413.     if (lNewPos > fStat.st_size)
  2414.         return ERROR_ACCESS_DENIED;
  2415.  
  2416.     /* Seek the file to new location */
  2417.     
  2418.     if ((lPosition = lseek (iFileDesc, lNewPos, SEEK_SET)) < 0)
  2419.     {
  2420.         !fDebug ? 0 : printf ("SetFilePosition: lseek failed, errno=%d, lPosition=%d, iFileDesc=%d, lNewPos=%d\n", 
  2421.             errno, lPosition, iFileDesc, lNewPos); 
  2422.  
  2423.         return MapWindowsError(errno);
  2424.     }
  2425.  
  2426.     if (lPosition != lNewPos)
  2427.         return ERROR_ACCESS_DENIED;
  2428.  
  2429.     return 0;
  2430. }
  2431.  
  2432.  
  2433.  
  2434.  
  2435.  
  2436.  
  2437.  
  2438.  
  2439.  
  2440.  
  2441.  
  2442.  
  2443.  
  2444.  
  2445.  
  2446.  
  2447.  
  2448.  
  2449.  
  2450.  
  2451.  
  2452.  
  2453.  
  2454.  
  2455.  
  2456.  
  2457.  
  2458.  
  2459.  
  2460.  
  2461.